stdlib_lapack_eigv_gen.fypp Source File


Source Code

#:include "common.fypp" 
submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_eigv_gen
  implicit none


  contains
#:for ik,it,ii in LINALG_INT_KINDS_TYPES

     module subroutine stdlib${ii}$_sgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, &
     !! SGEEV computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, &
                     minwrk, nout
           real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -9_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_strevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else if( wantvr ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_strevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    call stdlib${ii}$_shseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_sgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = ibal + n
           iwrk = itau + n
           call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_shseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 4*n, prefer n + n + 2*n*nb)
              call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_sgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_sgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_isamax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sgeev

     module subroutine stdlib${ii}$_dgeev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, &
     !! DGEEV computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, &
                     minwrk, nout
           real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -9_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_dtrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else if( wantvr ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_dtrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    call stdlib${ii}$_dhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_dgebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = ibal + n
           iwrk = itau + n
           call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_dhseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 4*n, prefer n + n + 2*n*nb)
              call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_dgebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_dgebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_idamax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dgeev

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$geev( jobvl, jobvr, n, a, lda, wr, wi, vl, ldvl, vr,ldvr, work, lwork, &
     !! DGEEV: computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), wi(*), work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, itau, iwrk, k, lwork_trevc, maxwrk, &
                     minwrk, nout
           real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(${rk}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -9_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_${ri}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else if( wantvr ) then
                    minwrk = 4_${ik}$*n
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                    call stdlib${ii}$_${ri}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr, n, nout,&
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    maxwrk = max( maxwrk, 4_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                    hswork = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + 1_${ik}$, n + hswork )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ri}$gebal( 'B', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = ibal + n
           iwrk = itau + n
           call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (workspace: need n+1, prefer n+hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 4*n, prefer n + n + 2*n*nb)
              call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_${ri}$gebak( 'B', 'L', n, ilo, ihi, work( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (workspace: need n)
              call stdlib${ii}$_${ri}$gebak( 'B', 'R', n, ilo, ihi, work( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( iwrk+k-1 ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_i${ri}$amax( n, work( iwrk ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$geev

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, &
     !! CGEEV computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, &
                     maxwrk, minwrk, nout
           real(sp) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(sp) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -8_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 if( wantvl ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_ctrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_ctrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    call stdlib${ii}$_chseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 maxwrk = max( maxwrk, hswork, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_cgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_chseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need 2*n)
              irwork = ibal + n
              call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_cgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_cgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_isamax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_cgeev

     module subroutine stdlib${ii}$_zgeev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, &
     !! ZGEEV computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, &
                     maxwrk, minwrk, nout
           real(dp) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(dp) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -8_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 if( wantvl ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_ztrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_ztrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    call stdlib${ii}$_zhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 maxwrk = max( maxwrk, hswork, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_zgebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_zhseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need 2*n)
              irwork = ibal + n
              call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_zgebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_zgebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_idamax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_zgeev

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$geev( jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr,work, lwork, rwork, &
     !! ZGEEV: computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
               info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr
           character :: side
           integer(${ik}$) :: hswork, i, ibal, ierr, ihi, ilo, irwork, itau, iwrk, k, lwork_trevc, &
                     maxwrk, minwrk, nout
           real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(${ck}$) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(${ck}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -8_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 if( wantvl ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_${ci}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    call stdlib${ii}$_${ci}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 maxwrk = max( maxwrk, hswork, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ci}$gebal( 'B', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need 2*n)
              irwork = ibal + n
              call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork( irwork ), n, ierr )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_${ci}$gebak( 'B', 'L', n, ilo, ihi, rwork( ibal ), n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_${ci}$gebak( 'B', 'R', n, ilo, ihi, rwork( ibal ), n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( irwork+k-1 ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )&
                              **2_${ik}$
                 end do
                 k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork( irwork ), 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( irwork+k-1 ) )
                 call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info>0_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ci}$geev

#:endif
#:endfor



     module subroutine stdlib${ii}$_sgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, &
     !! SGEEVX computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_sp of the LAPACK
     !! Users' Guide.
               ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(sp), intent(out) :: abnrm
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),&
                      work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(sp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. &
                     stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_strevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                 else if( wantvr ) then
                    call stdlib${ii}$_strevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_shseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_shseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    else
                       call stdlib${ii}$_shseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, 3_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_sgebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (workspace: need 2*n, prefer n+n*nb)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_slacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_shseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_shseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 3*n, prefer n + 2*n*nb)
              call stdlib${ii}$_strevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           ! compute condition numbers if desired
           ! (workspace: need n*n+6*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_strsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, iwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_sgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_isamax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_slartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_srot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_sgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_slapy2( stdlib${ii}$_snrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_snrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_sscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_isamax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_slartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_srot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sgeevx

     module subroutine stdlib${ii}$_dgeevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, &
     !! DGEEVX computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_dp of the LAPACK
     !! Users' Guide.
               ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(dp), intent(out) :: abnrm
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),&
                      work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(dp) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. &
                     stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_dtrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                 else if( wantvr ) then
                    call stdlib${ii}$_dtrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_dhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_dhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    else
                       call stdlib${ii}$_dhseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, 3_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_dgebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (workspace: need 2*n, prefer n+n*nb)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_dlacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_dhseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_dhseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 3*n, prefer n + 2*n*nb)
              call stdlib${ii}$_dtrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           ! compute condition numbers if desired
           ! (workspace: need n*n+6*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_dtrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, iwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_dgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_idamax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_dlartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_drot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_dgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_dlapy2( stdlib${ii}$_dnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_dnrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_dscal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_idamax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_dlartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_drot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dgeevx

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, wr, wi,vl, ldvl, vr, ldvr, &
     !! DGEEVX: computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate-transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_${rk}$ of the LAPACK
     !! Users' Guide.
               ilo, ihi, scale, abnrm,rconde, rcondv, work, lwork, iwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(${rk}$), intent(out) :: abnrm
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: rconde(*), rcondv(*), scale(*), vl(ldvl,*), vr(ldvr,*), wi(*),&
                      work(*), wr(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(${rk}$) :: anrm, bignum, cs, cscale, eps, r, scl, smlnum, sn
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(${rk}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ).or. &
                     stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_${ri}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vl, ldvl,work, -1_${ik}$, &
                              info )
                 else if( wantvr ) then
                    call stdlib${ii}$_${ri}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, n + lwork_trevc )
                    call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, wr, wi, vr, ldvr,work, -1_${ik}$, &
                              info )
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_${ri}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    else
                       call stdlib${ii}$_${ri}$hseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, wr, wi, vr,ldvr, work, -1_${ik}$, &
                                 info )
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.wntsnn )minwrk = max( minwrk, n*n+6*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.wntsnn )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                 else
                    minwrk = 3_${ik}$*n
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )minwrk = max( minwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( ( .not.wntsnn ) .and. ( .not.wntsne ) )maxwrk = max( maxwrk, n*n + 6_${ik}$*n )
                              
                    maxwrk = max( maxwrk, 3_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_${ri}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (workspace: need 2*n, prefer n+n*nb)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate orthogonal matrix in vl
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vl, ldvl,work( iwrk ), &
                        lwork-iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_${ri}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate orthogonal matrix in vr
              ! (workspace: need 2*n-1, prefer n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (workspace: need 1, prefer hswork (see comments) )
              iwrk = itau
              call stdlib${ii}$_${ri}$hseqr( job, 'N', n, ilo, ihi, a, lda, wr, wi, vr, ldvr,work( iwrk ), &
                        lwork-iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_${ri}$hseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (workspace: need 3*n, prefer n + 2*n*nb)
              call stdlib${ii}$_${ri}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1, ierr )
           end if
           ! compute condition numbers if desired
           ! (workspace: need n*n+6*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_${ri}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, iwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_${ri}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, &
                              vl( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vl( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vl( k, i )**2_${ik}$ + vl( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_${ri}$lartg( vl( k, i ), vl( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_${ri}$rot( n, vl( 1_${ik}$, i ), 1_${ik}$, vl( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vl( k, i+1 ) = zero
                 end if
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_${ri}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 if( wi( i )==zero ) then
                    scl = one / stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 else if( wi( i )>zero ) then
                    scl = one / stdlib${ii}$_${ri}$lapy2( stdlib${ii}$_${ri}$nrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( n, &
                              vr( 1_${ik}$, i+1 ), 1_${ik}$ ) )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$scal( n, scl, vr( 1_${ik}$, i+1 ), 1_${ik}$ )
                    do k = 1, n
                       work( k ) = vr( k, i )**2_${ik}$ + vr( k, i+1 )**2_${ik}$
                    end do
                    k = stdlib${ii}$_i${ri}$amax( n, work, 1_${ik}$ )
                    call stdlib${ii}$_${ri}$lartg( vr( k, i ), vr( k, i+1 ), cs, sn, r )
                    call stdlib${ii}$_${ri}$rot( n, vr( 1_${ik}$, i ), 1_${ik}$, vr( 1_${ik}$, i+1 ), 1_${ik}$, cs, sn )
                    vr( k, i+1 ) = zero
                 end if
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wr( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, wi( info+1 ),max( n-info, 1_${ik}$ &
                        ), ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wr, n,ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$geevx

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, &
     !! CGEEVX computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_sp of the LAPACK
     !! Users' Guide.
               ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(sp), intent(out) :: abnrm
           ! Array Arguments 
           real(sp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*)
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(sp) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(sp) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) &
                     .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -10_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_ctrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    call stdlib${ii}$_ctrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_chseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_chseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    else
                       call stdlib${ii}$_chseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                 else
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, 2_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -20_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_cgebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_clacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_chseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_chseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need n)
              call stdlib${ii}$_ctrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork, n, ierr )
           end if
           ! compute condition numbers if desired
           ! (cworkspace: need n*n+2*n unless sense = 'e')
           ! (rworkspace: need 2*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_ctrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, rwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_cgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_scnrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_csscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vl( k, i ),KIND=sp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_cscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=sp), zero,KIND=sp)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_cgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_scnrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_csscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vr( k, i ),KIND=sp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_isamax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_cscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=sp), zero,KIND=sp)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_cgeevx

     module subroutine stdlib${ii}$_zgeevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, &
     !! ZGEEVX computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_dp of the LAPACK
     !! Users' Guide.
               ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(dp), intent(out) :: abnrm
           ! Array Arguments 
           real(dp), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*)
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(dp) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(dp) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) &
                     .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -10_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_ztrevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    call stdlib${ii}$_ztrevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_zhseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_zhseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    else
                       call stdlib${ii}$_zhseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                 else
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, 2_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -20_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_zgebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_zlacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_zhseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_zhseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need n)
              call stdlib${ii}$_ztrevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork, n, ierr )
           end if
           ! compute condition numbers if desired
           ! (cworkspace: need n*n+2*n unless sense = 'e')
           ! (rworkspace: need 2*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_ztrsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, rwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_zgebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_dznrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_zdscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vl( k, i ),KIND=dp)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_zscal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=dp), zero,KIND=dp)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_zgebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_dznrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_zdscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vr( k, i ),KIND=dp)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_idamax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_zscal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=dp), zero,KIND=dp)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_zgeevx

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$geevx( balanc, jobvl, jobvr, sense, n, a, lda, w, vl,ldvl, vr, ldvr, ilo, &
     !! ZGEEVX: computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues and, optionally, the left and/or right eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! SCALE, and ABNRM), reciprocal condition numbers for the eigenvalues
     !! (RCONDE), and reciprocal condition numbers for the right
     !! eigenvectors (RCONDV).
     !! The right eigenvector v(j) of A satisfies
     !! A * v(j) = lambda(j) * v(j)
     !! where lambda(j) is its eigenvalue.
     !! The left eigenvector u(j) of A satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H
     !! where u(j)**H denotes the conjugate transpose of u(j).
     !! The computed eigenvectors are normalized to have Euclidean norm
     !! equal to 1 and largest component real.
     !! Balancing a matrix means permuting the rows and columns to make it
     !! more nearly upper triangular, and applying a diagonal similarity
     !! transformation D * A * D**(-1), where D is a diagonal matrix, to
     !! make its rows and columns closer in norm and the condition numbers
     !! of its eigenvalues and eigenvectors smaller.  The computed
     !! reciprocal condition numbers correspond to the balanced matrix.
     !! Permuting rows and columns will not change the condition numbers
     !! (in exact arithmetic) but diagonal scaling will.  For further
     !! explanation of balancing, see section 4.10.2_${ck}$ of the LAPACK
     !! Users' Guide.
               ihi, scale, abnrm, rconde,rcondv, work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldvl, ldvr, lwork, n
           real(${ck}$), intent(out) :: abnrm
           ! Array Arguments 
           real(${ck}$), intent(out) :: rconde(*), rcondv(*), rwork(*), scale(*)
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: vl(ldvl,*), vr(ldvr,*), w(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantvl, wantvr, wntsnb, wntsne, wntsnn, wntsnv
           character :: job, side
           integer(${ik}$) :: hswork, i, icond, ierr, itau, iwrk, k, lwork_trevc, maxwrk, minwrk, &
                     nout
           real(${ck}$) :: anrm, bignum, cscale, eps, scl, smlnum
           complex(${ck}$) :: tmp
           ! Local Arrays 
           logical(lk) :: select(1_${ik}$)
           real(${ck}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvl = stdlib_lsame( jobvl, 'V' )
           wantvr = stdlib_lsame( jobvr, 'V' )
           wntsnn = stdlib_lsame( sense, 'N' )
           wntsne = stdlib_lsame( sense, 'E' )
           wntsnv = stdlib_lsame( sense, 'V' )
           wntsnb = stdlib_lsame( sense, 'B' )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'S' ) &
                     .or.stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantvl ) .and. ( .not.stdlib_lsame( jobvl, 'N' ) ) ) then
              info = -2_${ik}$
           else if( ( .not.wantvr ) .and. ( .not.stdlib_lsame( jobvr, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wntsnn .or. wntsne .or. wntsnb .or. wntsnv ) .or.( ( wntsne .or. &
                     wntsnb ) .and. .not.( wantvl .and.wantvr ) ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( wantvl .and. ldvl<n ) ) then
              info = -10_${ik}$
           else if( ldvr<1_${ik}$ .or. ( wantvr .and. ldvr<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 if( wantvl ) then
                    call stdlib${ii}$_${ci}$trevc3( 'L', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vl, ldvl,work, -1_${ik}$, info )
                              
                 else if( wantvr ) then
                    call stdlib${ii}$_${ci}$trevc3( 'R', 'B', select, n, a, lda,vl, ldvl, vr, ldvr,n, nout, &
                              work, -1_${ik}$, rwork, -1_${ik}$, ierr )
                    lwork_trevc = int( work(1_${ik}$),KIND=${ik}$)
                    maxwrk = max( maxwrk, lwork_trevc )
                    call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                              
                 else
                    if( wntsnn ) then
                       call stdlib${ii}$_${ci}$hseqr( 'E', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    else
                       call stdlib${ii}$_${ci}$hseqr( 'S', 'N', n, 1_${ik}$, n, a, lda, w, vr, ldvr,work, -1_${ik}$, info )
                                 
                    end if
                 end if
                 hswork = int( work(1_${ik}$),KIND=${ik}$)
                 if( ( .not.wantvl ) .and. ( .not.wantvr ) ) then
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                 else
                    minwrk = 2_${ik}$*n
                    if( .not.( wntsnn .or. wntsne ) )minwrk = max( minwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, hswork )
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    if( .not.( wntsnn .or. wntsne ) )maxwrk = max( maxwrk, n*n + 2_${ik}$*n )
                    maxwrk = max( maxwrk, 2_${ik}$*n )
                 end if
                 maxwrk = max( maxwrk, minwrk )
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -20_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           icond = 0_${ik}$
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! balance the matrix and compute abnrm
           call stdlib${ii}$_${ci}$gebal( balanc, n, a, lda, ilo, ihi, scale, ierr )
           abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, dum )
           if( scalea ) then
              dum( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
              abnrm = dum( 1_${ik}$ )
           end if
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = itau + n
           call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvl ) then
              ! want left eigenvectors
              ! copy householder vectors to vl
              side = 'L'
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vl, ldvl )
              ! generate unitary matrix in vl
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vl, ldvl, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vl
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vl, ldvl,work( iwrk ), lwork-&
                        iwrk+1, info )
              if( wantvr ) then
                 ! want left and right eigenvectors
                 ! copy schur vectors to vr
                 side = 'B'
                 call stdlib${ii}$_${ci}$lacpy( 'F', n, n, vl, ldvl, vr, ldvr )
              end if
           else if( wantvr ) then
              ! want right eigenvectors
              ! copy householder vectors to vr
              side = 'R'
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vr, ldvr )
              ! generate unitary matrix in vr
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vr, ldvr, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
              ! perform qr iteration, accumulating schur vectors in vr
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( 'S', 'V', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           else
              ! compute eigenvalues only
              ! if condition numbers desired, compute schur form
              if( wntsnn ) then
                 job = 'E'
              else
                 job = 'S'
              end if
              ! (cworkspace: need 1, prefer hswork (see comments) )
              ! (rworkspace: none)
              iwrk = itau
              call stdlib${ii}$_${ci}$hseqr( job, 'N', n, ilo, ihi, a, lda, w, vr, ldvr,work( iwrk ), lwork-&
                        iwrk+1, info )
           end if
           ! if info /= 0 from stdlib${ii}$_${ci}$hseqr, then quit
           if( info/=0 )go to 50
           if( wantvl .or. wantvr ) then
              ! compute left and/or right eigenvectors
              ! (cworkspace: need 2*n, prefer n + 2*n*nb)
              ! (rworkspace: need n)
              call stdlib${ii}$_${ci}$trevc3( side, 'B', select, n, a, lda, vl, ldvl, vr, ldvr,n, nout, work(&
                         iwrk ), lwork-iwrk+1,rwork, n, ierr )
           end if
           ! compute condition numbers if desired
           ! (cworkspace: need n*n+2*n unless sense = 'e')
           ! (rworkspace: need 2*n unless sense = 'e')
           if( .not.wntsnn ) then
              call stdlib${ii}$_${ci}$trsna( sense, 'A', select, n, a, lda, vl, ldvl, vr, ldvr,rconde, &
                        rcondv, n, nout, work( iwrk ), n, rwork,icond )
           end if
           if( wantvl ) then
              ! undo balancing of left eigenvectors
              call stdlib${ii}$_${ci}$gebak( balanc, 'L', n, ilo, ihi, scale, n, vl, ldvl,ierr )
              ! normalize left eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vl( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$dscal( n, scl, vl( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vl( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vl( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vl( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_${ci}$scal( n, tmp, vl( 1_${ik}$, i ), 1_${ik}$ )
                 vl( k, i ) = cmplx( real( vl( k, i ),KIND=${ck}$), zero,KIND=${ck}$)
              end do
           end if
           if( wantvr ) then
              ! undo balancing of right eigenvectors
              call stdlib${ii}$_${ci}$gebak( balanc, 'R', n, ilo, ihi, scale, n, vr, ldvr,ierr )
              ! normalize right eigenvectors and make largest component real
              do i = 1, n
                 scl = one / stdlib${ii}$_${c2ri(ci)}$znrm2( n, vr( 1_${ik}$, i ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$dscal( n, scl, vr( 1_${ik}$, i ), 1_${ik}$ )
                 do k = 1, n
                    rwork( k ) = real( vr( k, i ),KIND=${ck}$)**2_${ik}$ +aimag( vr( k, i ) )**2_${ik}$
                 end do
                 k = stdlib${ii}$_i${c2ri(ci)}$amax( n, rwork, 1_${ik}$ )
                 tmp = conjg( vr( k, i ) ) / sqrt( rwork( k ) )
                 call stdlib${ii}$_${ci}$scal( n, tmp, vr( 1_${ik}$, i ), 1_${ik}$ )
                 vr( k, i ) = cmplx( real( vr( k, i ),KIND=${ck}$), zero,KIND=${ck}$)
              end do
           end if
           ! undo scaling if necessary
           50 continue
           if( scalea ) then
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-info, 1_${ik}$, w( info+1 ),max( n-info, 1_${ik}$ )&
                        , ierr )
              if( info==0_${ik}$ ) then
                 if( ( wntsnv .or. wntsnb ) .and. icond==0_${ik}$ )call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale,&
                            anrm, n, 1_${ik}$, rcondv, n,ierr )
              else
                 call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, w, n, ierr )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ci}$geevx

#:endif
#:endfor



     module subroutine stdlib${ii}$_sgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, &
     !! SGEES computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A matrix is in real Schur form if it is upper quasi-triangular with
     !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the
     !! form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_s) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, maxwrk, minwrk
           real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_shseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (workspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (workspace: none needed)
              call stdlib${ii}$_strsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, &
                        work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond )
              if( icond>0_${ik}$ )info = n + icond
           end if
           if( wantvs ) then
              ! undo balancing
              ! (workspace: need n)
              call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ )
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), &
                              ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                             call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              ! undo scaling for the imaginary part of the eigenvalues
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sgees

     module subroutine stdlib${ii}$_dgees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, &
     !! DGEES computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A matrix is in real Schur form if it is upper quasi-triangular with
     !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the
     !! form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_d) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, maxwrk, minwrk
           real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_dhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (workspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (workspace: none needed)
              call stdlib${ii}$_dtrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, &
                        work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond )
              if( icond>0_${ik}$ )info = n + icond
           end if
           if( wantvs ) then
              ! undo balancing
              ! (workspace: need n)
              call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ )
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), &
                              ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                             call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              ! undo scaling for the imaginary part of the eigenvalues
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dgees

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$gees( jobvs, sort, select, n, a, lda, sdim, wr, wi,vs, ldvs, work, lwork, &
     !! DGEES: computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A matrix is in real Schur form if it is upper quasi-triangular with
     !! 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the
     !! form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_${ri}$) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, maxwrk, minwrk
           real(${rk}$) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(${rk}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -13_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (workspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (workspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (workspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (workspace: none needed)
              call stdlib${ii}$_${ri}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, s, sep, &
                        work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,icond )
              if( icond>0_${ik}$ )info = n + icond
           end if
           if( wantvs ) then
              ! undo balancing
              ! (workspace: need n)
              call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ )
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi,max( ilo-1, 1_${ik}$ ), &
                              ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                             call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              ! undo scaling for the imaginary part of the eigenvalues
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$gees

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, &
     !! CGEES computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A complex matrix is in Schur form if it is upper triangular.
               rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_c) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, &
                     minwrk
           real(sp) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_chseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=sp)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (cworkspace: none)
              ! (rworkspace: none)
              call stdlib${ii}$_ctrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( &
                        iwrk ), lwork-iwrk+1, icond )
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_cgees

     module subroutine stdlib${ii}$_zgees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, &
     !! ZGEES computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A complex matrix is in Schur form if it is upper triangular.
               rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_z) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, &
                     minwrk
           real(dp) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_zhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=dp)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (cworkspace: none)
              ! (rworkspace: none)
              call stdlib${ii}$_ztrsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( &
                        iwrk ), lwork-iwrk+1, icond )
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_zgees

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$gees( jobvs, sort, select, n, a, lda, sdim, w, vs,ldvs, work, lwork, &
     !! ZGEES: computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left.
     !! The leading columns of Z then form an orthonormal basis for the
     !! invariant subspace corresponding to the selected eigenvalues.
     !! A complex matrix is in Schur form if it is upper triangular.
               rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_${ci}$) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantst, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, maxwrk, &
                     minwrk
           real(${ck}$) :: anrm, bignum, cscale, eps, s, sep, smlnum
           ! Local Arrays 
           real(${ck}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -6_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -10_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=${ck}$)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues and transform schur vectors
              ! (cworkspace: none)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$trsen( 'N', jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,s, sep, work( &
                        iwrk ), lwork-iwrk+1, icond )
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ci}$gees

#:endif
#:endfor



     module subroutine stdlib${ii}$_sgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, &
     !! SGEESX computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A real matrix is in real Schur form if it is upper quasi-triangular
     !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in
     !! the form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               rconde, rcondv, work, lwork,iwork, liwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n
           real(sp), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_s) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, &
                     wantsv, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, lwrk, liwrk, maxwrk, minwrk
           real(sp) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "rworkspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! iworkspace refers to integer workspace.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_shseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_strsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              liwrk = 1_${ik}$
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_shseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'SORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ )
                 if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwrk
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -16_${ik}$
              else if( liwork<1_${ik}$ .and. .not.lquery ) then
                 info = -18_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_sgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (rworkspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_slacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_sorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (rworkspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_shseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim)
                           ! otherwise, need n )
              ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim)
                           ! otherwise, need 0 )
              call stdlib${ii}$_strsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond )
              if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) )
              if( icond==-15_${ik}$ ) then
                 ! not enough real workspace
                 info = -16_${ik}$
              else if( icond==-17_${ik}$ ) then
                 ! not enough integer workspace
                 info = -18_${ik}$
              else if( icond>0_${ik}$ ) then
                 ! stdlib${ii}$_strsen failed to reorder or to restore standard schur form
                 info = icond + n
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (rworkspace: need n)
              call stdlib${ii}$_sgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_scopy( n, a, lda+1, wr, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_sswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_sswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                            call stdlib${ii}$_sswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           if( wantsv .or. wantsb ) then
              iwork( 1_${ik}$ ) = sdim*(n-sdim)
           else
              iwork( 1_${ik}$ ) = 1_${ik}$
           end if
           return
     end subroutine stdlib${ii}$_sgeesx

     module subroutine stdlib${ii}$_dgeesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, &
     !! DGEESX computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A real matrix is in real Schur form if it is upper quasi-triangular
     !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in
     !! the form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               rconde, rcondv, work, lwork,iwork, liwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n
           real(dp), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_d) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, &
                     wantsv, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, liwrk, lwrk, maxwrk, minwrk
           real(dp) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "rworkspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! iworkspace refers to integer workspace.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_dhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_dtrsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              liwrk = 1_${ik}$
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_dhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ )
                 if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwrk
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -16_${ik}$
              else if( liwork<1_${ik}$ .and. .not.lquery ) then
                 info = -18_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_dgebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (rworkspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_dlacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_dorghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (rworkspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_dhseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim)
                           ! otherwise, need n )
              ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim)
                           ! otherwise, need 0 )
              call stdlib${ii}$_dtrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond )
              if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) )
              if( icond==-15_${ik}$ ) then
                 ! not enough real workspace
                 info = -16_${ik}$
              else if( icond==-17_${ik}$ ) then
                 ! not enough integer workspace
                 info = -18_${ik}$
              else if( icond>0_${ik}$ ) then
                 ! stdlib${ii}$_dtrsen failed to reorder or to restore standard schur form
                 info = icond + n
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (rworkspace: need n)
              call stdlib${ii}$_dgebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_dcopy( n, a, lda+1, wr, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_dswap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_dswap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                            call stdlib${ii}$_dswap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           if( wantsv .or. wantsb ) then
              iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) )
           else
              iwork( 1_${ik}$ ) = 1_${ik}$
           end if
           return
     end subroutine stdlib${ii}$_dgeesx

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$geesx( jobvs, sort, select, sense, n, a, lda, sdim,wr, wi, vs, ldvs, &
     !! DGEESX: computes for an N-by-N real nonsymmetric matrix A, the
     !! eigenvalues, the real Schur form T, and, optionally, the matrix of
     !! Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! real Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_${rk}$ of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A real matrix is in real Schur form if it is upper quasi-triangular
     !! with 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in
     !! the form
     !! [  a  b  ]
     !! [  c  a  ]
     !! where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
               rconde, rcondv, work, lwork,iwork, liwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, liwork, lwork, n
           real(${rk}$), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: vs(ldvs,*), wi(*), work(*), wr(*)
           ! Function Arguments 
           procedure(stdlib_select_${ri}$) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, lastsl, lquery, lst2sl, scalea, wantsb, wantse, wantsn, wantst, &
                     wantsv, wantvs
           integer(${ik}$) :: hswork, i, i1, i2, ibal, icond, ierr, ieval, ihi, ilo, inxt, ip, itau, &
                     iwrk, liwrk, lwrk, maxwrk, minwrk
           real(${rk}$) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(${rk}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -12_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "rworkspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! iworkspace refers to integer workspace.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ri}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_${ri}$trsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              liwrk = 1_${ik}$
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = 2_${ik}$*n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 3_${ik}$*n
                 call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, wr, wi, vs, ldvs,work, -1_${ik}$, &
                           ieval )
                 hswork = work( 1_${ik}$ )
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, n + hswork )
                 else
                    maxwrk = max( maxwrk, 2_${ik}$*n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$,'DORGHR', ' ', n, 1_${ik}$, n,&
                               -1_${ik}$ ) )
                    maxwrk = max( maxwrk, n + hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, n + ( n*n )/2_${ik}$ )
                 if( wantsv .or. wantsb )liwrk = ( n*n )/4_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwrk
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -16_${ik}$
              else if( liwork<1_${ik}$ .and. .not.lquery ) then
                 info = -18_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ri}$gebal( 'P', n, a, lda, ilo, ihi, work( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (rworkspace: need 3*n, prefer 2*n+n*nb)
           itau = n + ibal
           iwrk = n + itau
           call stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_${ri}$lacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate orthogonal matrix in vs
              ! (rworkspace: need 3*n-1, prefer 2*n+(n-1)*nb)
              call stdlib${ii}$_${ri}$orghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (rworkspace: need n+1, prefer n+hswork (see comments) )
           iwrk = itau
           call stdlib${ii}$_${ri}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, wr, wi, vs, ldvs,work( iwrk ), &
                     lwork-iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wr, n, ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, wi, n, ierr )
              end if
              do i = 1, n
                 bwork( i ) = select( wr( i ), wi( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (rworkspace: if sense is not 'n', need n+2*sdim*(n-sdim)
                           ! otherwise, need n )
              ! (iworkspace: if sense is 'v' or 'b', need sdim*(n-sdim)
                           ! otherwise, need 0 )
              call stdlib${ii}$_${ri}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, wr, wi,sdim, rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,iwork, liwork, icond )
              if( .not.wantsn )maxwrk = max( maxwrk, n+2*sdim*( n-sdim ) )
              if( icond==-15_${ik}$ ) then
                 ! not enough real workspace
                 info = -16_${ik}$
              else if( icond==-17_${ik}$ ) then
                 ! not enough integer workspace
                 info = -18_${ik}$
              else if( icond>0_${ik}$ ) then
                 ! stdlib${ii}$_${ri}$trsen failed to reorder or to restore standard schur form
                 info = icond + n
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (rworkspace: need n)
              call stdlib${ii}$_${ri}$gebak( 'P', 'R', n, ilo, ihi, work( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ri}$copy( n, a, lda+1, wr, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
              if( cscale==smlnum ) then
                 ! if scaling back towards underflow, adjust wi if an
                 ! offdiagonal element of a 2-by-2 block in the schur form
                 ! underflows.
                 if( ieval>0_${ik}$ ) then
                    i1 = ieval + 1_${ik}$
                    i2 = ihi - 1_${ik}$
                    call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, ilo-1, 1_${ik}$, wi, n,ierr )
                 else if( wantst ) then
                    i1 = 1_${ik}$
                    i2 = n - 1_${ik}$
                 else
                    i1 = ilo
                    i2 = ihi - 1_${ik}$
                 end if
                 inxt = i1 - 1_${ik}$
                 loop_20: do i = i1, i2
                    if( i<inxt )cycle loop_20
                    if( wi( i )==zero ) then
                       inxt = i + 1_${ik}$
                    else
                       if( a( i+1, i )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                       else if( a( i+1, i )/=zero .and. a( i, i+1 )==zero ) then
                          wi( i ) = zero
                          wi( i+1 ) = zero
                          if( i>1_${ik}$ )call stdlib${ii}$_${ri}$swap( i-1, a( 1_${ik}$, i ), 1_${ik}$, a( 1_${ik}$, i+1 ), 1_${ik}$ )
                          if( n>i+1 )call stdlib${ii}$_${ri}$swap( n-i-1, a( i, i+2 ), lda,a( i+1, i+2 ), &
                                    lda )
                          if( wantvs ) then
                            call stdlib${ii}$_${ri}$swap( n, vs( 1_${ik}$, i ), 1_${ik}$, vs( 1_${ik}$, i+1 ), 1_${ik}$ )
                          end if
                          a( i, i+1 ) = a( i+1, i )
                          a( i+1, i ) = zero
                       end if
                       inxt = i + 2_${ik}$
                    end if
                 end do loop_20
              end if
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n-ieval, 1_${ik}$,wi( ieval+1 ), max( n-ieval,&
                         1_${ik}$ ), ierr )
           end if
           if( wantst .and. info==0_${ik}$ ) then
              ! check if reordering successful
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = select( wr( i ), wi( i ) )
                 if( wi( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           work( 1_${ik}$ ) = maxwrk
           if( wantsv .or. wantsb ) then
              iwork( 1_${ik}$ ) = max( 1_${ik}$, sdim*( n-sdim ) )
           else
              iwork( 1_${ik}$ ) = 1_${ik}$
           end if
           return
     end subroutine stdlib${ii}$_${ri}$geesx

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, &
     !! CGEESX computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_sp of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A complex matrix is in Schur form if it is upper triangular.
               rcondv, work, lwork, rwork,bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           real(sp), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_c) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, &
                     maxwrk, minwrk
           real(sp) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(sp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_chseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_ctrsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_chseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=sp)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ )
              end if
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -15_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_cgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_clacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_cunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_chseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim)
                           ! otherwise, need none )
              ! (rworkspace: none)
              call stdlib${ii}$_ctrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,icond )
              if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( icond==-14_${ik}$ ) then
                 ! not enough complex workspace
                 info = -15_${ik}$
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_cgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_ccopy( n, a, lda+1, w, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_cgeesx

     module subroutine stdlib${ii}$_zgeesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, &
     !! ZGEESX computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_dp of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A complex matrix is in Schur form if it is upper triangular.
               rcondv, work, lwork, rwork,bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           real(dp), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_z) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, &
                     maxwrk, minwrk
           real(dp) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(dp) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_zhseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_ztrsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_zhseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=dp)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ )
              end if
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -15_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_zgebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_zlacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_zunghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_zhseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim)
                           ! otherwise, need none )
              ! (rworkspace: none)
              call stdlib${ii}$_ztrsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,icond )
              if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( icond==-14_${ik}$ ) then
                 ! not enough complex workspace
                 info = -15_${ik}$
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_zgebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_zcopy( n, a, lda+1, w, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_zgeesx

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$geesx( jobvs, sort, select, sense, n, a, lda, sdim, w,vs, ldvs, rconde, &
     !! ZGEESX: computes for an N-by-N complex nonsymmetric matrix A, the
     !! eigenvalues, the Schur form T, and, optionally, the matrix of Schur
     !! vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
     !! Optionally, it also orders the eigenvalues on the diagonal of the
     !! Schur form so that selected eigenvalues are at the top left;
     !! computes a reciprocal condition number for the average of the
     !! selected eigenvalues (RCONDE); and computes a reciprocal condition
     !! number for the right invariant subspace corresponding to the
     !! selected eigenvalues (RCONDV).  The leading columns of Z form an
     !! orthonormal basis for this invariant subspace.
     !! For further explanation of the reciprocal condition numbers RCONDE
     !! and RCONDV, see Section 4.10_${ck}$ of the LAPACK Users' Guide (where
     !! these quantities are called s and sep respectively).
     !! A complex matrix is in Schur form if it is upper triangular.
               rcondv, work, lwork, rwork,bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvs, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldvs, lwork, n
           real(${ck}$), intent(out) :: rconde, rcondv
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: vs(ldvs,*), w(*), work(*)
           ! Function Arguments 
           procedure(stdlib_select_${ci}$) :: select
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery, scalea, wantsb, wantse, wantsn, wantst, wantsv, wantvs
           integer(${ik}$) :: hswork, i, ibal, icond, ierr, ieval, ihi, ilo, itau, iwrk, lwrk, &
                     maxwrk, minwrk
           real(${ck}$) :: anrm, bignum, cscale, eps, smlnum
           ! Local Arrays 
           real(${ck}$) :: dum(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           wantvs = stdlib_lsame( jobvs, 'V' )
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ )
           if( ( .not.wantvs ) .and. ( .not.stdlib_lsame( jobvs, 'N' ) ) ) then
              info = -1_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -2_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvs<1_${ik}$ .or. ( wantvs .and. ldvs<n ) ) then
              info = -11_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of real workspace needed at that point in the
             ! code, as well as the preferred amount for good performance.
             ! cworkspace refers to complex workspace, and rworkspace to real
             ! workspace. nb refers to the optimal block size for the
             ! immediately following subroutine, as returned by stdlib${ii}$_ilaenv.
             ! hswork refers to the workspace preferred by stdlib${ii}$_${ci}$hseqr, as
             ! calculated below. hswork is computed assuming ilo=1 and ihi=n,
             ! the worst case.
             ! if sense = 'e', 'v' or 'b', then the amount of workspace needed
             ! depends on sdim, which is computed by the routine stdlib${ii}$_${ci}$trsen later
             ! in the code.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 lwrk = 1_${ik}$
              else
                 maxwrk = n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 minwrk = 2_${ik}$*n
                 call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, 1_${ik}$, n, a, lda, w, vs, ldvs,work, -1_${ik}$, ieval )
                           
                 hswork = real( work( 1_${ik}$ ),KIND=${ck}$)
                 if( .not.wantvs ) then
                    maxwrk = max( maxwrk, hswork )
                 else
                    maxwrk = max( maxwrk, n + ( n - 1_${ik}$ )*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGHR',' ', n, 1_${ik}$, n, -&
                              1_${ik}$ ) )
                    maxwrk = max( maxwrk, hswork )
                 end if
                 lwrk = maxwrk
                 if( .not.wantsn )lwrk = max( lwrk, ( n*n )/2_${ik}$ )
              end if
              work( 1_${ik}$ ) = lwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -15_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEESX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, dum )
           scalea = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              scalea = .true.
              cscale = smlnum
           else if( anrm>bignum ) then
              scalea = .true.
              cscale = bignum
           end if
           if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, cscale, n, n, a, lda, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (cworkspace: none)
           ! (rworkspace: need n)
           ibal = 1_${ik}$
           call stdlib${ii}$_${ci}$gebal( 'P', n, a, lda, ilo, ihi, rwork( ibal ), ierr )
           ! reduce to upper hessenberg form
           ! (cworkspace: need 2*n, prefer n+n*nb)
           ! (rworkspace: none)
           itau = 1_${ik}$
           iwrk = n + itau
           call stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, work( itau ), work( iwrk ),lwork-iwrk+1, ierr &
                     )
           if( wantvs ) then
              ! copy householder vectors to vs
              call stdlib${ii}$_${ci}$lacpy( 'L', n, n, a, lda, vs, ldvs )
              ! generate unitary matrix in vs
              ! (cworkspace: need 2*n-1, prefer n+(n-1)*nb)
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$unghr( n, ilo, ihi, vs, ldvs, work( itau ), work( iwrk ),lwork-iwrk+1, &
                        ierr )
           end if
           sdim = 0_${ik}$
           ! perform qr iteration, accumulating schur vectors in vs if desired
           ! (cworkspace: need 1, prefer hswork (see comments) )
           ! (rworkspace: none)
           iwrk = itau
           call stdlib${ii}$_${ci}$hseqr( 'S', jobvs, n, ilo, ihi, a, lda, w, vs, ldvs,work( iwrk ), lwork-&
                     iwrk+1, ieval )
           if( ieval>0_${ik}$ )info = ieval
           ! sort eigenvalues if desired
           if( wantst .and. info==0_${ik}$ ) then
              if( scalea )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, n, 1_${ik}$, w, n, ierr )
              do i = 1, n
                 bwork( i ) = select( w( i ) )
              end do
              ! reorder eigenvalues, transform schur vectors, and compute
              ! reciprocal condition numbers
              ! (cworkspace: if sense is not 'n', need 2*sdim*(n-sdim)
                           ! otherwise, need none )
              ! (rworkspace: none)
              call stdlib${ii}$_${ci}$trsen( sense, jobvs, bwork, n, a, lda, vs, ldvs, w, sdim,rconde, &
                        rcondv, work( iwrk ), lwork-iwrk+1,icond )
              if( .not.wantsn )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( icond==-14_${ik}$ ) then
                 ! not enough complex workspace
                 info = -15_${ik}$
              end if
           end if
           if( wantvs ) then
              ! undo balancing
              ! (cworkspace: none)
              ! (rworkspace: need n)
              call stdlib${ii}$_${ci}$gebak( 'P', 'R', n, ilo, ihi, rwork( ibal ), n, vs, ldvs,ierr )
           end if
           if( scalea ) then
              ! undo scaling for the schur form of a
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, cscale, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ci}$copy( n, a, lda+1, w, 1_${ik}$ )
              if( ( wantsv .or. wantsb ) .and. info==0_${ik}$ ) then
                 dum( 1_${ik}$ ) = rcondv
                 call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, cscale, anrm, 1_${ik}$, 1_${ik}$, dum, 1_${ik}$, ierr )
                 rcondv = dum( 1_${ik}$ )
              end if
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ci}$geesx

#:endif
#:endfor



     module subroutine stdlib${ii}$_sggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,&
     !! SGGEV3 computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
                ldvr, work, lwork,info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then
              info = -16_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_sgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_sormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_sgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, &
                        -1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_sorgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_slaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_slaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = real( lwkopt,KIND=sp)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_sgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk, ierr )
           else
              call stdlib${ii}$_sgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_slaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = real( lwkopt,KIND=sp)
           return
     end subroutine stdlib${ii}$_sggev3

     module subroutine stdlib${ii}$_dggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,&
     !! DGGEV3 computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
                ldvr, work, lwork,info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then
              info = -16_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_dgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max(1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_dormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work, -1_${ik}$,ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_dorgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              if( ilv ) then
                 call stdlib${ii}$_dgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_dlaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_dgghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -&
                           1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_dlaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_dgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk, ierr )
           else
              call stdlib${ii}$_dgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_dlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_dggev3

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$ggev3( jobvl, jobvr, n, a, lda, b, ldb, alphar,alphai, beta, vl, ldvl, vr,&
     !! DGGEV3: computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
                ldvr, work, lwork,info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, lwkopt
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           else if( lwork<max( 1_${ik}$, 8_${ik}$*n ) .and. .not.lquery ) then
              info = -16_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_${ri}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max(1_${ik}$, 8_${ik}$*n, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ri}$ormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work, -1_${ik}$,ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_${ri}$orgqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              if( ilv ) then
                 call stdlib${ii}$_${ri}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_${ri}$laqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_${ri}$gghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -&
                           1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_${ri}$laqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                           beta, vl, ldvl, vr, ldvr,work, -1_${ik}$, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ri}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk, ierr )
           else
              call stdlib${ii}$_${ri}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ri}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ri}$ggev3

#:endif
#:endfor

     module subroutine stdlib${ii}$_cggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! CGGEV3 computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(sp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(sp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -15_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_cgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( n,  n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_cunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_cungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              if( ilv ) then
                 call stdlib${ii}$_cgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_claqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_cgghd3( 'N', 'N', n, 1_${ik}$, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, work, -&
                           1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_claqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'E' )*stdlib${ii}$_slamch( 'B' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_cgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk,ierr )
           else
              call stdlib${ii}$_cgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_claqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp)
           return
     end subroutine stdlib${ii}$_cggev3

     module subroutine stdlib${ii}$_zggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! ZGGEV3 computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(dp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(dp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -15_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_zgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$,  n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_zunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_zungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              if( ilv ) then
                 call stdlib${ii}$_zgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_zlaqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_zgghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_zlaqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'E' )*stdlib${ii}$_dlamch( 'B' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_zgghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk, ierr )
           else
              call stdlib${ii}$_zgghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_zlaqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp)
           return
     end subroutine stdlib${ii}$_zggev3

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$ggev3( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! ZGGEV3: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkopt
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(${ck}$) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(${ck}$) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -15_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_${ci}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$,  n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ci}$unmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvl ) then
                 call stdlib${ii}$_${ci}$ungqr( n, n, n, vl, ldvl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              if( ilv ) then
                 call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_${ci}$laqz0( 'S', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              else
                 call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                           work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
                 call stdlib${ii}$_${ci}$laqz0( 'E', jobvl, jobvr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vl, &
                           ldvl, vr, ldvr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
                 lwkopt = max( lwkopt, n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEV3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'E' )*stdlib${ii}$_${c2ri(ci)}$lamch( 'B' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           if( ilvl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ci}$gghd3( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        work( iwrk ), lwork+1-iwrk, ierr )
           else
              call stdlib${ii}$_${ci}$gghd3( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ci}$laqz0( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              if( ilvl ) then
                 call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$)
           return
     end subroutine stdlib${ii}$_${ci}$ggev3

#:endif
#:endfor



     module subroutine stdlib${ii}$_sggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, &
     !! SGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
               ldvr, work, lwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, maxwrk, minwrk
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              minwrk = max( 1_${ik}$, 8_${ik}$*n )
              maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
              maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
                        
              if( ilvl ) then
                 maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           ! (workspace: need 6*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sggev

     module subroutine stdlib${ii}$_dggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, &
     !! DGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
               ldvr, work, lwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, maxwrk, minwrk
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              minwrk = max( 1_${ik}$, 8_${ik}$*n )
              maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
              maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
                        
              if( ilvl ) then
                 maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           ! (workspace: need 6*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dggev

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$ggev( jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai,beta, vl, ldvl, vr, &
     !! DGGEV: computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B .
     !! where u(j)**H is the conjugate-transpose of u(j).
               ldvr, work, lwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
                     
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, itau, &
                     iwrk, jc, jr, maxwrk, minwrk
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -12_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -14_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              minwrk = max( 1_${ik}$, 8_${ik}$*n )
              maxwrk = max( 1_${ik}$, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
              maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) ) )
                        
              if( ilvl ) then
                 maxwrk = max( maxwrk, n*( 7_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -16_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 110
           end if
           ! compute eigenvectors
           ! (workspace: need 6*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 110
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, vl, &
                           ldvl, ierr )
                 loop_50: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_50
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_50
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vl( jr, jc ) = vl( jr, jc )*temp
                          vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_50
              end if
              if( ilvr ) then
                 call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, vr, &
                           ldvr, ierr )
                 loop_100: do jc = 1, n
                    if( alphai( jc )<zero )cycle loop_100
                    temp = zero
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) ) )
                       end do
                    else
                       do jr = 1, n
                          temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                       end do
                    end if
                    if( temp<smlnum )cycle loop_100
                    temp = one / temp
                    if( alphai( jc )==zero ) then
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                       end do
                    else
                       do jr = 1, n
                          vr( jr, jc ) = vr( jr, jc )*temp
                          vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                       end do
                    end if
                 end do loop_100
              end if
              ! end of eigenvector calculation
           end if
           ! undo scaling if necessary
           110 continue
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$ggev

#:endif
#:endfor

     module subroutine stdlib${ii}$_cggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! CGGEV computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkmin, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(sp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(sp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              if( ilvl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'E' )*stdlib${ii}$_slamch( 'B' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           ! (real workspace: need 2*n)
           ! (complex workspace: need 2*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_cggev

     module subroutine stdlib${ii}$_zggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! ZGGEV computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkmin, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(dp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(dp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              if( ilvl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'E' )*stdlib${ii}$_dlamch( 'B' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           ! (real workspace: need 2*n)
           ! (complex workspace: need 2*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_zggev

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$ggev( jobvl, jobvr, n, a, lda, b, ldb, alpha, beta,vl, ldvl, vr, ldvr, &
     !! ZGGEV: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right generalized eigenvector v(j) corresponding to the
     !! generalized eigenvalue lambda(j) of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j).
     !! The left generalized eigenvector u(j) corresponding to the
     !! generalized eigenvalues lambda(j) of (A,B) satisfies
     !! u(j)**H * A = lambda(j) * u(j)**H * B
     !! where u(j)**H is the conjugate-transpose of u(j).
               work, lwork, rwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvl, jobvr
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           ! Array Arguments 
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery
           character :: chtemp
           integer(${ik}$) :: icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, in, iright, irows, irwrk,&
                      itau, iwrk, jc, jr, lwkmin, lwkopt
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(${ck}$) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(${ck}$) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -11_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              if( ilvl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -15_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEV ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'E' )*stdlib${ii}$_${c2ri(ci)}$lamch( 'B' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrices a, b to isolate eigenvalues if possible
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           if( ilv ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vr
           if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           if( ilv ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur form and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 70
           end if
           ! compute eigenvectors
           ! (real workspace: need 2*n)
           ! (complex workspace: need 2*n)
           if( ilv ) then
              if( ilvl ) then
                 if( ilvr ) then
                    chtemp = 'B'
                 else
                    chtemp = 'L'
                 end if
              else
                 chtemp = 'R'
              end if
              call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl, ldvl,vr, ldvr, n, &
                        in, work( iwrk ), rwork( irwrk ),ierr )
              if( ierr/=0_${ik}$ ) then
                 info = n + 2_${ik}$
                 go to 70
              end if
              ! undo balancing on vl and vr and normalization
              ! (workspace: none needed)
              if( ilvl ) then
                 call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vl,&
                            ldvl, ierr )
                 loop_30: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vl( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_30
                    temp = one / temp
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 end do loop_30
              end if
              if( ilvr ) then
                 call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), n, vr,&
                            ldvr, ierr )
                 loop_60: do jc = 1, n
                    temp = zero
                    do jr = 1, n
                       temp = max( temp, abs1( vr( jr, jc ) ) )
                    end do
                    if( temp<smlnum )cycle loop_60
                    temp = one / temp
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 end do loop_60
              end if
           end if
           ! undo scaling if necessary
           70 continue
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ci}$ggev

#:endif
#:endfor



     module subroutine stdlib${ii}$_sggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, &
     !! SGGEVX computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(sp), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)&
                     , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, &
                     wantsn, wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk, mm
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( noscl .or. stdlib_lsame( balanc, 'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) &
                     then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -14_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 if( noscl .and. .not.ilv ) then
                    minwrk = 2_${ik}$*n
                 else
                    minwrk = 6_${ik}$*n
                 end if
                 if( wantse ) then
                    minwrk = 10_${ik}$*n
                 else if( wantsv .or. wantsb ) then
                    minwrk = 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -26_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_sggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_slange( '1', n, n, a, lda, work( 1_${ik}$ ) )
           if( ilascl ) then
              work( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = work( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_slange( '1', n, n, b, ldb, work( 1_${ik}$ ) )
           if( ilbscl ) then
              work( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = work( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_sgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_sgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_shgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr, work,lwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 130
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! (workspace: stdlib${ii}$_stgevc: need 6*n
                       ! stdlib${ii}$_stgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b',
                               ! need n otherwise )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_stgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work, ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 130
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_stgevc) and estimate condition
                 ! numbers (stdlib${ii}$_stgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to recalculate
                 ! eigenvectors and estimate one condition numbers at a time.
                 pair = .false.
                 loop_20: do i = 1, n
                    if( pair ) then
                       pair = .false.
                       cycle loop_20
                    end if
                    mm = 1_${ik}$
                    if( i<n ) then
                       if( a( i+1, i )/=zero ) then
                          pair = .true.
                          mm = 2_${ik}$
                       end if
                    end if
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    if( mm==1_${ik}$ ) then
                       bwork( i ) = .true.
                    else if( mm==2_${ik}$ ) then
                       bwork( i ) = .true.
                       bwork( i+1 ) = .true.
                    end if
                    iwrk = mm*n + 1_${ik}$
                    iwrk1 = iwrk + mm*n
                    ! compute a pair of left and right eigenvectors.
                    ! (compute workspace: need up to 4*n + 6*n)
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_stgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, mm, m,work( iwrk1 ), ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 130
                       end if
                    end if
                    call stdlib${ii}$_stgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,&
                               ierr )
                 end do loop_20
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_sggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_70: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_70
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_70
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                       vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_70
           end if
           if( ilvr ) then
              call stdlib${ii}$_sggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_120: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_120
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_120
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                       vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_120
           end if
           ! undo scaling if necessary
           130 continue
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sggevx

     module subroutine stdlib${ii}$_dggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, &
     !! DGGEVX computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(dp), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)&
                     , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, &
                     wantsn, wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk, mm
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc,'S' ) .or. &
                     stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -14_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 if( noscl .and. .not.ilv ) then
                    minwrk = 2_${ik}$*n
                 else
                    minwrk = 6_${ik}$*n
                 end if
                 if( wantse .or. wantsb ) then
                    minwrk = 10_${ik}$*n
                 end if
                 if( wantsv .or. wantsb ) then
                    minwrk = max( minwrk, 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$ )
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -26_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_dggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_dlange( '1', n, n, a, lda, work( 1_${ik}$ ) )
           if( ilascl ) then
              work( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = work( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_dlange( '1', n, n, b, ldb, work( 1_${ik}$ ) )
           if( ilbscl ) then
              work( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = work( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_dgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_dgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_dhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr, work,lwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 130
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! (workspace: stdlib${ii}$_dtgevc: need 6*n
                       ! stdlib${ii}$_dtgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b',
                               ! need n otherwise )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_dtgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work, ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 130
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_dtgevc) and estimate condition
                 ! numbers (stdlib${ii}$_dtgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to recalculate
                 ! eigenvectors and estimate one condition numbers at a time.
                 pair = .false.
                 loop_20: do i = 1, n
                    if( pair ) then
                       pair = .false.
                       cycle loop_20
                    end if
                    mm = 1_${ik}$
                    if( i<n ) then
                       if( a( i+1, i )/=zero ) then
                          pair = .true.
                          mm = 2_${ik}$
                       end if
                    end if
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    if( mm==1_${ik}$ ) then
                       bwork( i ) = .true.
                    else if( mm==2_${ik}$ ) then
                       bwork( i ) = .true.
                       bwork( i+1 ) = .true.
                    end if
                    iwrk = mm*n + 1_${ik}$
                    iwrk1 = iwrk + mm*n
                    ! compute a pair of left and right eigenvectors.
                    ! (compute workspace: need up to 4*n + 6*n)
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_dtgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, mm, m,work( iwrk1 ), ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 130
                       end if
                    end if
                    call stdlib${ii}$_dtgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,&
                               ierr )
                 end do loop_20
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_dggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_70: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_70
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_70
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                       vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_70
           end if
           if( ilvr ) then
              call stdlib${ii}$_dggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_120: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_120
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_120
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                       vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_120
           end if
           ! undo scaling if necessary
           130 continue
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dggevx

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$ggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alphar, alphai, &
     !! DGGEVX: computes for a pair of N-by-N real nonsymmetric matrices (A,B)
     !! the generalized eigenvalues, and optionally, the left and/or right
     !! generalized eigenvectors.
     !! Optionally also, it computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     beta, vl, ldvl, vr, ldvr, ilo,ihi, lscale, rscale, abnrm, bbnrm, rconde,rcondv, work, lwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(${rk}$), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), lscale(*), rconde(*), rcondv(*)&
                     , rscale(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, pair, wantsb, wantse, &
                     wantsn, wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk, mm
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc,'S' ) .or. &
                     stdlib_lsame( balanc, 'P' ) .or. stdlib_lsame( balanc, 'B' ) ) )then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -14_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 if( noscl .and. .not.ilv ) then
                    minwrk = 2_${ik}$*n
                 else
                    minwrk = 6_${ik}$*n
                 end if
                 if( wantse .or. wantsb ) then
                    minwrk = 10_${ik}$*n
                 end if
                 if( wantsv .or. wantsb ) then
                    minwrk = max( minwrk, 2_${ik}$*n*( n + 4_${ik}$ ) + 16_${ik}$ )
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -26_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           smlnum = stdlib${ii}$_${ri}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${ri}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_${ri}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,work, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_${ri}$lange( '1', n, n, a, lda, work( 1_${ik}$ ) )
           if( ilascl ) then
              work( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = work( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_${ri}$lange( '1', n, n, b, ldb, work( 1_${ik}$ ) )
           if( ilbscl ) then
              work( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, work( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = work( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ri}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_${ri}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (workspace: need n)
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ri}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vl, ldvl, vr, ldvr, work,lwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 130
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! (workspace: stdlib${ii}$_${ri}$tgevc: need 6*n
                       ! stdlib${ii}$_${ri}$tgsna: need 2*n*(n+2)+16 if sense = 'v' or 'b',
                               ! need n otherwise )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_${ri}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work, ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 130
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_${ri}$tgevc) and estimate condition
                 ! numbers (stdlib${ii}$_${ri}$tgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to recalculate
                 ! eigenvectors and estimate one condition numbers at a time.
                 pair = .false.
                 loop_20: do i = 1, n
                    if( pair ) then
                       pair = .false.
                       cycle loop_20
                    end if
                    mm = 1_${ik}$
                    if( i<n ) then
                       if( a( i+1, i )/=zero ) then
                          pair = .true.
                          mm = 2_${ik}$
                       end if
                    end if
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    if( mm==1_${ik}$ ) then
                       bwork( i ) = .true.
                    else if( mm==2_${ik}$ ) then
                       bwork( i ) = .true.
                       bwork( i+1 ) = .true.
                    end if
                    iwrk = mm*n + 1_${ik}$
                    iwrk1 = iwrk + mm*n
                    ! compute a pair of left and right eigenvectors.
                    ! (compute workspace: need up to 4*n + 6*n)
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_${ri}$tgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, mm, m,work( iwrk1 ), ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 130
                       end if
                    end if
                    call stdlib${ii}$_${ri}$tgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), mm, m, work( iwrk1 ),lwork-iwrk1+1, iwork,&
                               ierr )
                 end do loop_20
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_${ri}$ggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_70: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_70
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vl( jr, jc ) )+abs( vl( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_70
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vl( jr, jc ) = vl( jr, jc )*temp
                       vl( jr, jc+1 ) = vl( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_70
           end if
           if( ilvr ) then
              call stdlib${ii}$_${ri}$ggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_120: do jc = 1, n
                 if( alphai( jc )<zero )cycle loop_120
                 temp = zero
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) ) )
                    end do
                 else
                    do jr = 1, n
                       temp = max( temp, abs( vr( jr, jc ) )+abs( vr( jr, jc+1 ) ) )
                    end do
                 end if
                 if( temp<smlnum )cycle loop_120
                 temp = one / temp
                 if( alphai( jc )==zero ) then
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                    end do
                 else
                    do jr = 1, n
                       vr( jr, jc ) = vr( jr, jc )*temp
                       vr( jr, jc+1 ) = vr( jr, jc+1 )*temp
                    end do
                 end if
              end do loop_120
           end if
           ! undo scaling if necessary
           130 continue
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$ggevx

#:endif
#:endfor

     module subroutine stdlib${ii}$_cggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, &
     !! CGGEVX computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B) the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! Optionally, it also computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(sp), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, &
                     wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(sp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(sp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=sp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) &
                     then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -13_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -15_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 minwrk = 2_${ik}$*n
                 if( wantse ) then
                    minwrk = 4_${ik}$*n
                 else if( wantsv .or. wantsb ) then
                    minwrk = 2_${ik}$*n*( n + 1_${ik}$)
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -25_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_cggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_clange( '1', n, n, a, lda, rwork( 1_${ik}$ ) )
           if( ilascl ) then
              rwork( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = rwork( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_clange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) )
           if( ilbscl ) then
              rwork( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = rwork( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_cgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_cgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_chgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 90
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! stdlib${ii}$_ctgevc: (complex workspace: need 2*n )
                   ! (real workspace:    need 2*n )
           ! stdlib${ii}$_ctgsna: (complex workspace: need 2*n*n if sense='v' or 'b')
                   ! (integer workspace: need n+2 )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_ctgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work( iwrk ), rwork,ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 90
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_ctgevc) and estimate condition
                 ! numbers (stdlib${ii}$_ctgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to
                 ! re-calculate eigenvectors and estimate the condition numbers
                 ! one at a time.
                 do i = 1, n
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    bwork( i ) = .true.
                    iwrk = n + 1_${ik}$
                    iwrk1 = iwrk + n
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_ctgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 90
                       end if
                    end if
                    call stdlib${ii}$_ctgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, &
                              ierr )
                 end do
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_cggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_50: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vl( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_50
                 temp = one / temp
                 do jr = 1, n
                    vl( jr, jc ) = vl( jr, jc )*temp
                 end do
              end do loop_50
           end if
           if( ilvr ) then
              call stdlib${ii}$_cggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_80: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vr( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_80
                 temp = one / temp
                 do jr = 1, n
                    vr( jr, jc ) = vr( jr, jc )*temp
                 end do
              end do loop_80
           end if
           ! undo scaling if necessary
           90 continue
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_cggevx

     module subroutine stdlib${ii}$_zggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, &
     !! ZGGEVX computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B) the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! Optionally, it also computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(dp), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, &
                     wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(dp) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(dp) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=dp) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) &
                     then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -13_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -15_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 minwrk = 2_${ik}$*n
                 if( wantse ) then
                    minwrk = 4_${ik}$*n
                 else if( wantsv .or. wantsb ) then
                    minwrk = 2_${ik}$*n*( n + 1_${ik}$)
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -25_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_zggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_zlange( '1', n, n, a, lda, rwork( 1_${ik}$ ) )
           if( ilascl ) then
              rwork( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = rwork( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_zlange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) )
           if( ilbscl ) then
              rwork( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = rwork( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_zgghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_zgghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_zhgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 90
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! stdlib${ii}$_ztgevc: (complex workspace: need 2*n )
                   ! (real workspace:    need 2*n )
           ! stdlib${ii}$_ztgsna: (complex workspace: need 2*n*n if sense='v' or 'b')
                   ! (integer workspace: need n+2 )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_ztgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work( iwrk ), rwork,ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 90
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_ztgevc) and estimate condition
                 ! numbers (stdlib${ii}$_ztgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to
                 ! re-calculate eigenvectors and estimate the condition numbers
                 ! one at a time.
                 do i = 1, n
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    bwork( i ) = .true.
                    iwrk = n + 1_${ik}$
                    iwrk1 = iwrk + n
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_ztgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 90
                       end if
                    end if
                    call stdlib${ii}$_ztgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, &
                              ierr )
                 end do
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_zggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_50: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vl( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_50
                 temp = one / temp
                 do jr = 1, n
                    vl( jr, jc ) = vl( jr, jc )*temp
                 end do
              end do loop_50
           end if
           if( ilvr ) then
              call stdlib${ii}$_zggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_80: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vr( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_80
                 temp = one / temp
                 do jr = 1, n
                    vr( jr, jc ) = vr( jr, jc )*temp
                 end do
              end do loop_80
           end if
           ! undo scaling if necessary
           90 continue
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_zggevx

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$ggevx( balanc, jobvl, jobvr, sense, n, a, lda, b, ldb,alpha, beta, vl, &
     !! ZGGEVX: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B) the generalized eigenvalues, and optionally, the left and/or
     !! right generalized eigenvectors.
     !! Optionally, it also computes a balancing transformation to improve
     !! the conditioning of the eigenvalues and eigenvectors (ILO, IHI,
     !! LSCALE, RSCALE, ABNRM, and BBNRM), reciprocal condition numbers for
     !! the eigenvalues (RCONDE), and reciprocal condition numbers for the
     !! right eigenvectors (RCONDV).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar
     !! lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
     !! singular. It is usually represented as the pair (alpha,beta), as
     !! there is a reasonable interpretation for beta=0, and even for both
     !! being zero.
     !! The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! A * v(j) = lambda(j) * B * v(j) .
     !! The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
     !! of (A,B) satisfies
     !! u(j)**H * A  = lambda(j) * u(j)**H * B.
     !! where u(j)**H is the conjugate-transpose of u(j).
     ldvl, vr, ldvr, ilo, ihi,lscale, rscale, abnrm, bbnrm, rconde, rcondv,work, lwork, rwork, &
               iwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: balanc, jobvl, jobvr, sense
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, ldb, ldvl, ldvr, lwork, n
           real(${ck}$), intent(out) :: abnrm, bbnrm
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(${ck}$), intent(out) :: lscale(*), rconde(*), rcondv(*), rscale(*), rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vl(ldvl,*), vr(ldvr,*), work(*)
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: ilascl, ilbscl, ilv, ilvl, ilvr, lquery, noscl, wantsb, wantse, wantsn, &
                     wantsv
           character :: chtemp
           integer(${ik}$) :: i, icols, ierr, ijobvl, ijobvr, in, irows, itau, iwrk, iwrk1, j, jc, &
                     jr, m, maxwrk, minwrk
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, smlnum, temp
           complex(${ck}$) :: x
           ! Local Arrays 
           logical(lk) :: ldumma(1_${ik}$)
           ! Intrinsic Functions 
           ! Statement Functions 
           real(${ck}$) :: abs1
           ! Statement Function Definitions 
           abs1( x ) = abs( real( x,KIND=${ck}$) ) + abs( aimag( x ) )
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvl = .false.
           else if( stdlib_lsame( jobvl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvl = .true.
           else
              ijobvl = -1_${ik}$
              ilvl = .false.
           end if
           if( stdlib_lsame( jobvr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvr = .false.
           else if( stdlib_lsame( jobvr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvr = .true.
           else
              ijobvr = -1_${ik}$
              ilvr = .false.
           end if
           ilv = ilvl .or. ilvr
           noscl  = stdlib_lsame( balanc, 'N' ) .or. stdlib_lsame( balanc, 'P' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( .not.( noscl .or. stdlib_lsame( balanc,'S' ) .or.stdlib_lsame( balanc, 'B' ) ) ) &
                     then
              info = -1_${ik}$
           else if( ijobvl<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsb .or. wantsv ) )then
              info = -4_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvl<1_${ik}$ .or. ( ilvl .and. ldvl<n ) ) then
              info = -13_${ik}$
           else if( ldvr<1_${ik}$ .or. ( ilvr .and. ldvr<n ) ) then
              info = -15_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv. the workspace is
             ! computed assuming ilo = 1 and ihi = n, the worst case.)
           if( info==0_${ik}$ ) then
              if( n==0_${ik}$ ) then
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              else
                 minwrk = 2_${ik}$*n
                 if( wantse ) then
                    minwrk = 4_${ik}$*n
                 else if( wantsv .or. wantsb ) then
                    minwrk = 2_${ik}$*n*( n + 1_${ik}$)
                 end if
                 maxwrk = minwrk
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 maxwrk = max( maxwrk,n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                           
                 if( ilvl ) then
                    maxwrk = max( maxwrk, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                              
                 end if
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -25_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGEVX', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute and/or balance the matrix pair (a,b)
           ! (real workspace: need 6*n if balanc = 's' or 'b', 1 otherwise)
           call stdlib${ii}$_${ci}$ggbal( balanc, n, a, lda, b, ldb, ilo, ihi, lscale, rscale,rwork, ierr )
                     
           ! compute abnrm and bbnrm
           abnrm = stdlib${ii}$_${ci}$lange( '1', n, n, a, lda, rwork( 1_${ik}$ ) )
           if( ilascl ) then
              rwork( 1_${ik}$ ) = abnrm
              call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              abnrm = rwork( 1_${ik}$ )
           end if
           bbnrm = stdlib${ii}$_${ci}$lange( '1', n, n, b, ldb, rwork( 1_${ik}$ ) )
           if( ilbscl ) then
              rwork( 1_${ik}$ ) = bbnrm
              call stdlib${ii}$_${c2ri(ci)}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, 1_${ik}$, 1_${ik}$, rwork( 1_${ik}$ ), 1_${ik}$,ierr )
              bbnrm = rwork( 1_${ik}$ )
           end if
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb )
           irows = ihi + 1_${ik}$ - ilo
           if( ilv .or. .not.wantsn ) then
              icols = n + 1_${ik}$ - ilo
           else
              icols = irows
           end if
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vl and/or vr
           ! (workspace: need n, prefer n*nb)
           if( ilvl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vl, ldvl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vl( ilo+1, ilo ),&
                            ldvl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vl( ilo, ilo ), ldvl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           if( ilvr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vr, ldvr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           if( ilv .or. .not.wantsn ) then
              ! eigenvectors requested -- work on whole matrix.
              call stdlib${ii}$_${ci}$gghrd( jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb, vl,ldvl, vr, ldvr, &
                        ierr )
           else
              call stdlib${ii}$_${ci}$gghrd( 'N', 'N', irows, 1_${ik}$, irows, a( ilo, ilo ), lda,b( ilo, ilo ), &
                        ldb, vl, ldvl, vr, ldvr, ierr )
           end if
           ! perform qz algorithm (compute eigenvalues, and optionally, the
           ! schur forms and schur vectors)
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           if( ilv .or. .not.wantsn ) then
              chtemp = 'S'
           else
              chtemp = 'E'
           end if
           call stdlib${ii}$_${ci}$hgeqz( chtemp, jobvl, jobvr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vl, &
                     ldvl, vr, ldvr, work( iwrk ),lwork+1-iwrk, rwork, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 90
           end if
           ! compute eigenvectors and estimate condition numbers if desired
           ! stdlib${ii}$_${ci}$tgevc: (complex workspace: need 2*n )
                   ! (real workspace:    need 2*n )
           ! stdlib${ii}$_${ci}$tgsna: (complex workspace: need 2*n*n if sense='v' or 'b')
                   ! (integer workspace: need n+2 )
           if( ilv .or. .not.wantsn ) then
              if( ilv ) then
                 if( ilvl ) then
                    if( ilvr ) then
                       chtemp = 'B'
                    else
                       chtemp = 'L'
                    end if
                 else
                    chtemp = 'R'
                 end if
                 call stdlib${ii}$_${ci}$tgevc( chtemp, 'B', ldumma, n, a, lda, b, ldb, vl,ldvl, vr, ldvr, n,&
                            in, work( iwrk ), rwork,ierr )
                 if( ierr/=0_${ik}$ ) then
                    info = n + 2_${ik}$
                    go to 90
                 end if
              end if
              if( .not.wantsn ) then
                 ! compute eigenvectors (stdlib${ii}$_${ci}$tgevc) and estimate condition
                 ! numbers (stdlib${ii}$_${ci}$tgsna). note that the definition of the condition
                 ! number is not invariant under transformation (u,v) to
                 ! (q*u, z*v), where (u,v) are eigenvectors of the generalized
                 ! schur form (s,t), q and z are orthogonal matrices. in order
                 ! to avoid using extra 2*n*n workspace, we have to
                 ! re-calculate eigenvectors and estimate the condition numbers
                 ! one at a time.
                 do i = 1, n
                    do j = 1, n
                       bwork( j ) = .false.
                    end do
                    bwork( i ) = .true.
                    iwrk = n + 1_${ik}$
                    iwrk1 = iwrk + n
                    if( wantse .or. wantsb ) then
                       call stdlib${ii}$_${ci}$tgevc( 'B', 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                                 iwrk ), n, 1_${ik}$, m,work( iwrk1 ), rwork, ierr )
                       if( ierr/=0_${ik}$ ) then
                          info = n + 2_${ik}$
                          go to 90
                       end if
                    end if
                    call stdlib${ii}$_${ci}$tgsna( sense, 'S', bwork, n, a, lda, b, ldb,work( 1_${ik}$ ), n, work( &
                    iwrk ), n, rconde( i ),rcondv( i ), 1_${ik}$, m, work( iwrk1 ),lwork-iwrk1+1, iwork, &
                              ierr )
                 end do
              end if
           end if
           ! undo balancing on vl and vr and normalization
           ! (workspace: none needed)
           if( ilvl ) then
              call stdlib${ii}$_${ci}$ggbak( balanc, 'L', n, ilo, ihi, lscale, rscale, n, vl,ldvl, ierr )
                        
              loop_50: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vl( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_50
                 temp = one / temp
                 do jr = 1, n
                    vl( jr, jc ) = vl( jr, jc )*temp
                 end do
              end do loop_50
           end if
           if( ilvr ) then
              call stdlib${ii}$_${ci}$ggbak( balanc, 'R', n, ilo, ihi, lscale, rscale, n, vr,ldvr, ierr )
                        
              loop_80: do jc = 1, n
                 temp = zero
                 do jr = 1, n
                    temp = max( temp, abs1( vr( jr, jc ) ) )
                 end do
                 if( temp<smlnum )cycle loop_80
                 temp = one / temp
                 do jr = 1, n
                    vr( jr, jc ) = vr( jr, jc )*temp
                 end do
              end do loop_80
           end if
           ! undo scaling if necessary
           90 continue
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ci}$ggevx

#:endif
#:endfor



     module subroutine stdlib${ii}$_sgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, &
     !! SGGES3 computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! SGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_s) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then
              info = -19_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_sgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_sormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_sorgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_sgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_slaqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                        beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
                 beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr )
                           
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           safmin = stdlib${ii}$_slamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_slabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_sgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk, ierr )
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_slaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 40
           end if
           ! sort eigenvalues alpha/beta if desired
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl )then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphar( i ) )>( &
                              anrm/anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i )/alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphai( i ) )>( &
                              anrm/anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i+1 )/alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl )then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                     if( ( beta( i )/safmax )>( bnrmto/bnrm ) .or.( safmin/beta( i ) )>( &
                               bnrm/bnrmto ) ) then
                        work( 1_${ik}$ ) = abs(b( i, i )/beta( i ))
                        beta( i ) = beta( i )*work( 1_${ik}$ )
                        alphar( i ) = alphar( i )*work( 1_${ik}$ )
                        alphai( i ) = alphai( i )*work( 1_${ik}$ )
                     end if
                  end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           40 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_sgges3

     module subroutine stdlib${ii}$_dgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, &
     !! DGGES3 computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! DGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_d) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then
              info = -19_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_dgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_dormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_dorgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_dgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_dlaqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                        beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
                 beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr )
                           
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           safmin = stdlib${ii}$_dlamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_dlabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_dgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk,ierr )
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_dlaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 50
           end if
           ! sort eigenvalues alpha/beta if desired
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           50 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_dgges3

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$gges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alphar, &
     !! DGGES3: computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! DGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl,vsr, ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_${ri}$) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, lwkopt
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(${rk}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           else if( lwork<6_${ik}$*n+16 .and. .not.lquery ) then
              info = -19_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_${ri}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 6_${ik}$*n+16, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ri}$ormqr( 'L', 'T', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_${ri}$orgqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_${ri}$gghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, 3_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ri}$laqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alphar, alphai, &
                        beta, vsl, ldvsl, vsr, ldvsr,work, -1_${ik}$, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
                 beta, vsl, ldvsl, vsr, ldvsr,sdim, pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$,ierr )
                           
                 lwkopt = max( lwkopt, 2_${ik}$*n+int( work ( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           safmin = stdlib${ii}$_${ri}$lamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_${ri}$labad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_${ri}$gghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk,ierr )
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_${ri}$laqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 50
           end if
           ! sort eigenvalues alpha/beta if desired
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           50 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ri}$gges3

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, &
     !! CGGES3 computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! CGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_c) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -18_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_cgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$,  n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_cunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_cungqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$,ierr )
                 lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_cgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_claqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vsl, &
                        ldvsl, vsr, ldvsr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
                           ldvsl, vsr, ldvsr, sdim,pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$, ierr )
                 lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_cgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk, ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_claqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=sp)
           return
     end subroutine stdlib${ii}$_cgges3

     module subroutine stdlib${ii}$_zgges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, &
     !! ZGGES3 computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! ZGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_z) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -18_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_zgeqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$,  n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_zunmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_zungqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_zgghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_zlaqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vsl, &
                        ldvsl, vsr, ldvsr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_ztgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
                           ldvsl, vsr, ldvsr, sdim,pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$, ierr )
                 lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_zgghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk, ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_zlaqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_ztgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=dp)
           return
     end subroutine stdlib${ii}$_zgges3

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$gges3( jobvsl, jobvsr, sort, selctg, n, a, lda, b,ldb, sdim, alpha, beta, &
     !! ZGGES3: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! ZGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr,work, lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_${ci}$) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkopt
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(${ck}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           else if( lwork<max( 1_${ik}$, 2_${ik}$*n ) .and. .not.lquery ) then
              info = -18_${ik}$
           end if
           ! compute workspace
           if( info==0_${ik}$ ) then
              call stdlib${ii}$_${ci}$geqrf( n, n, b, ldb, work, work, -1_${ik}$, ierr )
              lwkopt = max( 1_${ik}$,  n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ci}$unmqr( 'L', 'C', n, n, n, b, ldb, work, a, lda, work,-1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( ilvsl ) then
                 call stdlib${ii}$_${ci}$ungqr( n, n, n, vsl, ldvsl, work, work, -1_${ik}$, ierr )
                 lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              call stdlib${ii}$_${ci}$gghd3( jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr, &
                        work, -1_${ik}$, ierr )
              lwkopt = max( lwkopt, n + int( work( 1_${ik}$ ),KIND=${ik}$) )
              call stdlib${ii}$_${ci}$laqz0( 'S', jobvsl, jobvsr, n, 1_${ik}$, n, a, lda, b, ldb,alpha, beta, vsl, &
                        ldvsl, vsr, ldvsr, work, -1_${ik}$,rwork, 0_${ik}$, ierr )
              lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              if( wantst ) then
                 call stdlib${ii}$_${ci}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
                           ldvsl, vsr, ldvsr, sdim,pvsl, pvsr, dif, work, -1_${ik}$, idum, 1_${ik}$, ierr )
                 lwkopt = max( lwkopt, int( work( 1_${ik}$ ),KIND=${ik}$) )
              end if
              work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$)
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGES3 ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           if( ilvsl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           call stdlib${ii}$_${ci}$gghd3( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      work( iwrk ), lwork+1-iwrk, ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           iwrk = itau
           call stdlib${ii}$_${ci}$laqz0( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), 0_${ik}$, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_${ci}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = cmplx( lwkopt,KIND=${ck}$)
           return
     end subroutine stdlib${ii}$_${ci}$gges3

#:endif
#:endfor



     module subroutine stdlib${ii}$_sgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, &
     !! SGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! SGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_s) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, maxwrk, minwrk
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$ )then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -19_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           safmin = stdlib${ii}$_slamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_slabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n space for storing balancing factors)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_sgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_shgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 40
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: need 4*n+16 )
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_stgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl )then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphar( i ) )>( &
                              anrm/anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i )/alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i )/safmax )>( anrmto/anrm ) .or.( safmin/alphai( i ) )>( &
                              anrm/anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i+1 )/alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl )then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                     if( ( beta( i )/safmax )>( bnrmto/bnrm ) .or.( safmin/beta( i ) )>( &
                               bnrm/bnrmto ) ) then
                        work( 1_${ik}$ ) = abs(b( i, i )/beta( i ))
                        beta( i ) = beta( i )*work( 1_${ik}$ )
                        alphar( i ) = alphar( i )*work( 1_${ik}$ )
                        alphai( i ) = alphai( i )*work( 1_${ik}$ )
                     end if
                  end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           40 continue
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_sgges

     module subroutine stdlib${ii}$_dgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, &
     !! DGGES computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! DGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_d) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, maxwrk, minwrk
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$ )then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -19_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           safmin = stdlib${ii}$_dlamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_dlabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n space for storing balancing factors)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_dgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_dhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 50
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: need 4*n+16 )
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_dtgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           50 continue
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_dgges

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$gges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alphar, &
     !! DGGES: computes for a pair of N-by-N real nonsymmetric matrices (A,B),
     !! the generalized eigenvalues, the generalized real Schur form (S,T),
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**T, (VSL)*T*(VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T.The
     !! leading columns of VSL and VSR then form an orthonormal basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! DGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
               alphai, beta, vsl, ldvsl, vsr,ldvsr, work, lwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), &
                     work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_${ri}$) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, &
                     wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, ip, iright, irows, &
                     itau, iwrk, maxwrk, minwrk
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(${rk}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$ )then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
              end if
              work( 1_${ik}$ ) = maxwrk
              if( lwork<minwrk .and. .not.lquery )info = -19_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           safmin = stdlib${ii}$_${ri}$lamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_${ri}$labad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n space for storing balancing factors)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_${ri}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_${ri}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 50
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: need 4*n+16 )
           sdim = 0_${ik}$
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              call stdlib${ii}$_${ri}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alphar,alphai, beta, &
              vsl, ldvsl, vsr, ldvsr, sdim, pvsl,pvsr, dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$,&
                        ierr )
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           50 continue
           work( 1_${ik}$ ) = maxwrk
           return
     end subroutine stdlib${ii}$_${ri}$gges

#:endif
#:endfor

     module subroutine stdlib${ii}$_cgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, &
     !! CGGES computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! CGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(sp), intent(out) :: rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_c) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkmin, lwkopt
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
              if( ilvsl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -18_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_cgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           call stdlib${ii}$_chgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: none needed)
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_ctgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_cgges

     module subroutine stdlib${ii}$_zgges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, &
     !! ZGGES computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! ZGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(dp), intent(out) :: rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_z) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkmin, lwkopt
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
              if( ilvsl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -18_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_zgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           call stdlib${ii}$_zhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: none needed)
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_ztgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_zgges

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$gges( jobvsl, jobvsr, sort, selctg, n, a, lda, b, ldb,sdim, alpha, beta, &
     !! ZGGES: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the generalized complex Schur
     !! form (S, T), and optionally left and/or right Schur vectors (VSL
     !! and VSR). This gives the generalized Schur factorization
     !! (A,B) = ( (VSL)*S*(VSR)**H, (VSL)*T*(VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T. The leading
     !! columns of VSL and VSR then form an unitary basis for the
     !! corresponding left and right eigenspaces (deflating subspaces).
     !! (If only the generalized eigenvalues are needed, use the driver
     !! ZGGEV instead, which is faster.)
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0, and even for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if S
     !! and T are upper triangular and, in addition, the diagonal elements
     !! of T are non-negative real numbers.
               vsl, ldvsl, vsr, ldvsr, work,lwork, rwork, bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           real(${ck}$), intent(out) :: rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_${ci}$) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantst
           integer(${ik}$) :: i, icols, ierr, ihi, ijobvl, ijobvr, ileft, ilo, iright, irows, irwrk, &
                     itau, iwrk, lwkmin, lwkopt
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pvsl, pvsr, smlnum
           ! Local Arrays 
           integer(${ik}$) :: idum(1_${ik}$)
           real(${ck}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -5_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -14_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -16_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              lwkmin = max( 1_${ik}$, 2_${ik}$*n )
              lwkopt = max( 1_${ik}$, n + n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
              lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
              if( ilvsl ) then
                 lwkopt = max( lwkopt, n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) )
                           
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery )info = -18_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGES ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_${ci}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace: need n)
           iwrk = itau
           call stdlib${ii}$_${ci}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 30
           end if
           ! sort eigenvalues alpha/beta if desired
           ! (workspace: none needed)
           if( wantst ) then
              ! undo scaling on eigenvalues before selecting
              if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              call stdlib${ii}$_${ci}$tgsen( 0_${ik}$, ilvsl, ilvsr, bwork, n, a, lda, b, ldb, alpha,beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pvsl, pvsr,dif, work( iwrk ), lwork-iwrk+1, idum, 1_${ik}$, ierr )
                        
              if( ierr==1_${ik}$ )info = n + 3_${ik}$
           end if
           ! apply back-permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           30 continue
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ci}$gges

#:endif
#:endfor



     module subroutine stdlib${ii}$_sggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, &
     !! SGGESX computes for a pair of N-by-N real nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and,
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
     alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, &
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(inout) :: a(lda,*), b(ldb,*)
           real(sp), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(&
                     ldvsl,*), vsr(ldvsr,*), work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_s) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, &
                     wantse, wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, &
                     irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -16_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -18_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 6_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -22_${ik}$
              else if( liwork<liwmin  .and. .not.lquery ) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           safmin = stdlib${ii}$_slamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_slabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_slange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_slange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n for permutation parameters)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_sggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_sgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_sormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_sorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_slaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_sgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_shgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 50
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) )
                       ! otherwise, need 8*(n+1) )
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              call stdlib${ii}$_stgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
              beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, &
                        liwork, ierr )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-22_${ik}$ ) then
                  ! not enough real workspace
                 info = -22_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_sggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_sggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ).or. ( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_slascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_slascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           50 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_sggesx

     module subroutine stdlib${ii}$_dggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, &
     !! DGGESX computes for a pair of N-by-N real nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and,
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
     alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, &
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(inout) :: a(lda,*), b(ldb,*)
           real(dp), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(&
                     ldvsl,*), vsr(ldvsr,*), work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_d) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, &
                     wantse, wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, &
                     irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -16_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -18_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 6_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -22_${ik}$
              else if( liwork<liwmin  .and. .not.lquery ) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           safmin = stdlib${ii}$_dlamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_dlabad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_dlange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_dlange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n for permutation parameters)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_dggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_dgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_dormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_dorgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_dlaset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_dgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_dhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 60
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) )
                       ! otherwise, need 8*(n+1) )
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              call stdlib${ii}$_dtgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
              beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, &
                        liwork, ierr )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-22_${ik}$ ) then
                  ! not enough real workspace
                 info = -22_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_dggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_dggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_dlascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_dlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           60 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_dggesx

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$ggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, &
     !! DGGESX: computes for a pair of N-by-N real nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the real Schur form (S,T), and,
     !! optionally, the left and/or right matrices of Schur vectors (VSL and
     !! VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T )
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! quasi-triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized real Schur form if T is
     !! upper triangular with non-negative diagonal and S is block upper
     !! triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
     !! to real generalized eigenvalues, while 2-by-2 blocks of S will be
     !! "standardized" by making the corresponding elements of T have the
     !! form:
     !! [  a  0  ]
     !! [  0  b  ]
     !! and the pair of corresponding 2-by-2 blocks in S and T will have a
     !! complex conjugate pair of generalized eigenvalues.
     alphar, alphai, beta, vsl, ldvsl,vsr, ldvsr, rconde, rcondv, work, lwork, iwork,liwork, &
               bwork, info )
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*)
           real(${rk}$), intent(out) :: alphai(*), alphar(*), beta(*), rconde(2_${ik}$), rcondv(2_${ik}$), vsl(&
                     ldvsl,*), vsr(ldvsr,*), work(*)
           ! Function Arguments 
           procedure(stdlib_selctg_${ri}$) :: selctg
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, lst2sl, wantsb, &
                     wantse, wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, ip, iright, &
                     irows, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(${rk}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, safmax, safmin, &
                     smlnum
           ! Local Arrays 
           real(${rk}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -16_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -18_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = max( 8_${ik}$*n, 6_${ik}$*n + 16_${ik}$ )
                 maxwrk = minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ )
                 maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ &
                           ) )
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, minwrk - n +n*stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', n, 1_${ik}$, n, &
                              -1_${ik}$ ) )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 6_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -22_${ik}$
              else if( liwork<liwmin  .and. .not.lquery ) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${ri}$lamch( 'P' )
           safmin = stdlib${ii}$_${ri}$lamch( 'S' )
           safmax = one / safmin
           call stdlib${ii}$_${ri}$labad( safmin, safmax )
           smlnum = sqrt( safmin ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ri}$lange( 'M', n, n, a, lda, work )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ri}$lange( 'M', n, n, b, ldb, work )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (workspace: need 6*n + 2*n for permutation parameters)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           iwrk = iright + n
           call stdlib${ii}$_${ri}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, work( ileft ),work( iright ), &
                     work( iwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = iwrk
           iwrk = itau + irows
           call stdlib${ii}$_${ri}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the orthogonal transformation to matrix a
           ! (workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ri}$ormqr( 'L', 'T', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ri}$orgqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ri}$laset( 'FULL', n, n, zero, one, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_${ri}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (workspace: need n)
           iwrk = itau
           call stdlib${ii}$_${ri}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alphar, alphai, &
                     beta, vsl, ldvsl, vsr, ldvsr,work( iwrk ), lwork+1-iwrk, ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 60
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           ! (workspace: if ijob >= 1, need max( 8*(n+1), 2*sdim*(n-sdim) )
                       ! otherwise, need 8*(n+1) )
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl ) then
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n,ierr )
                 call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n,ierr )
              end if
              if( ilbscl )call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alphar( i ), alphai( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              call stdlib${ii}$_${ri}$tgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alphar, alphai, &
              beta, vsl, ldvsl, vsr, ldvsr,sdim, pl, pr, dif, work( iwrk ), lwork-iwrk+1,iwork, &
                        liwork, ierr )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-22_${ik}$ ) then
                  ! not enough real workspace
                 info = -22_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_${ri}$ggbak( 'P', 'L', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ri}$ggbak( 'P', 'R', n, ilo, ihi, work( ileft ),work( iright ), n, &
                     vsr, ldvsr, ierr )
           ! check if unscaling would cause over/underflow, if so, rescale
           ! (alphar(i),alphai(i),beta(i)) so beta(i) is on the order of
           ! b(i,i) and alphar(i) and alphai(i) are on the order of a(i,i)
           if( ilascl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( alphar( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphar( i ) )>( &
                              anrm / anrmto ) ) then
                       work( 1_${ik}$ ) = abs( a( i, i ) / alphar( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    else if( ( alphai( i ) / safmax )>( anrmto / anrm ) .or.( safmin / alphai( i )&
                               )>( anrm / anrmto ) )then
                       work( 1_${ik}$ ) = abs( a( i, i+1 ) / alphai( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           if( ilbscl ) then
              do i = 1, n
                 if( alphai( i )/=zero ) then
                    if( ( beta( i ) / safmax )>( bnrmto / bnrm ) .or.( safmin / beta( i ) )>( &
                              bnrm / bnrmto ) ) then
                       work( 1_${ik}$ ) = abs( b( i, i ) / beta( i ) )
                       beta( i ) = beta( i )*work( 1_${ik}$ )
                       alphar( i ) = alphar( i )*work( 1_${ik}$ )
                       alphai( i ) = alphai( i )*work( 1_${ik}$ )
                    end if
                 end if
              end do
           end if
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ri}$lascl( 'H', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphar, n, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alphai, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ri}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              lst2sl = .true.
              sdim = 0_${ik}$
              ip = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alphar( i ), alphai( i ), beta( i ) )
                 if( alphai( i )==zero ) then
                    if( cursl )sdim = sdim + 1_${ik}$
                    ip = 0_${ik}$
                    if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 else
                    if( ip==1_${ik}$ ) then
                       ! last eigenvalue of conjugate pair
                       cursl = cursl .or. lastsl
                       lastsl = cursl
                       if( cursl )sdim = sdim + 2_${ik}$
                       ip = -1_${ik}$
                       if( cursl .and. .not.lst2sl )info = n + 2_${ik}$
                    else
                       ! first eigenvalue of conjugate pair
                       ip = 1_${ik}$
                    end if
                 end if
                 lst2sl = lastsl
                 lastsl = cursl
              end do
           end if
           60 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_${ri}$ggesx

#:endif
#:endfor

     module subroutine stdlib${ii}$_cggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,&
     !! CGGESX computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the complex Schur form (S,T),
     !! and, optionally, the left and/or right matrices of Schur vectors (VSL
     !! and VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if T is
     !! upper triangular with non-negative diagonal and S is upper
     !! triangular.
      beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info )
                
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*)
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(sp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_c) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, &
                     wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, &
                     irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(sp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum
           ! Local Arrays 
           real(sp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = 2_${ik}$*n
                 maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                 maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) &
                              )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 2_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              else if( liwork<liwmin  .and. .not.lquery) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_slamch( 'P' )
           smlnum = stdlib${ii}$_slamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_slabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_clange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_clange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_cggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_cgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_cunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_clacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_cungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_claset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_cgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace:    need n)
           iwrk = itau
           call stdlib${ii}$_chgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 40
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim))
                                  ! otherwise, need 1 )
              call stdlib${ii}$_ctgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr &
                        )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-21_${ik}$ ) then
                  ! not enough complex workspace
                 info = -21_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_cggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_cggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_clascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           40 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_cggesx

     module subroutine stdlib${ii}$_zggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,&
     !! ZGGESX computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the complex Schur form (S,T),
     !! and, optionally, the left and/or right matrices of Schur vectors (VSL
     !! and VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if T is
     !! upper triangular with non-negative diagonal and S is upper
     !! triangular.
      beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info )
                
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*)
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*)
           complex(dp), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_z) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, &
                     wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, &
                     irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(dp) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum
           ! Local Arrays 
           real(dp) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = 2_${ik}$*n
                 maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                 maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) &
                              )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 2_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              else if( liwork<liwmin  .and. .not.lquery) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_dlamch( 'P' )
           smlnum = stdlib${ii}$_dlamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_dlabad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_zlange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_zlange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_zggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_zgeqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_zunmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_zlacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_zungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_zlaset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_zgghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace:    need n)
           iwrk = itau
           call stdlib${ii}$_zhgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 40
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim))
                                  ! otherwise, need 1 )
              call stdlib${ii}$_ztgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr &
                        )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-21_${ik}$ ) then
                  ! not enough complex workspace
                 info = -21_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_zggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_zggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_zlascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           40 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_zggesx

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     module subroutine stdlib${ii}$_${ci}$ggesx( jobvsl, jobvsr, sort, selctg, sense, n, a, lda,b, ldb, sdim, alpha,&
     !! ZGGESX: computes for a pair of N-by-N complex nonsymmetric matrices
     !! (A,B), the generalized eigenvalues, the complex Schur form (S,T),
     !! and, optionally, the left and/or right matrices of Schur vectors (VSL
     !! and VSR).  This gives the generalized Schur factorization
     !! (A,B) = ( (VSL) S (VSR)**H, (VSL) T (VSR)**H )
     !! where (VSR)**H is the conjugate-transpose of VSR.
     !! Optionally, it also orders the eigenvalues so that a selected cluster
     !! of eigenvalues appears in the leading diagonal blocks of the upper
     !! triangular matrix S and the upper triangular matrix T; computes
     !! a reciprocal condition number for the average of the selected
     !! eigenvalues (RCONDE); and computes a reciprocal condition number for
     !! the right and left deflating subspaces corresponding to the selected
     !! eigenvalues (RCONDV). The leading columns of VSL and VSR then form
     !! an orthonormal basis for the corresponding left and right eigenspaces
     !! (deflating subspaces).
     !! A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
     !! or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
     !! usually represented as the pair (alpha,beta), as there is a
     !! reasonable interpretation for beta=0 or for both being zero.
     !! A pair of matrices (S,T) is in generalized complex Schur form if T is
     !! upper triangular with non-negative diagonal and S is upper
     !! triangular.
      beta, vsl, ldvsl, vsr,ldvsr, rconde, rcondv, work, lwork, rwork,iwork, liwork, bwork, info )
                
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: jobvsl, jobvsr, sense, sort
           integer(${ik}$), intent(out) :: info, sdim
           integer(${ik}$), intent(in) :: lda, ldb, ldvsl, ldvsr, liwork, lwork, n
           ! Array Arguments 
           logical(lk), intent(out) :: bwork(*)
           integer(${ik}$), intent(out) :: iwork(*)
           real(${ck}$), intent(out) :: rconde(2_${ik}$), rcondv(2_${ik}$), rwork(*)
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*)
           complex(${ck}$), intent(out) :: alpha(*), beta(*), vsl(ldvsl,*), vsr(ldvsr,*), work(*)
                     
           ! Function Arguments 
           procedure(stdlib_selctg_${ci}$) :: selctg
        ! =====================================================================
           
           
           ! Local Scalars 
           logical(lk) :: cursl, ilascl, ilbscl, ilvsl, ilvsr, lastsl, lquery, wantsb, wantse, &
                     wantsn, wantst, wantsv
           integer(${ik}$) :: i, icols, ierr, ihi, ijob, ijobvl, ijobvr, ileft, ilo, iright, irows, &
                     irwrk, itau, iwrk, liwmin, lwrk, maxwrk, minwrk
           real(${ck}$) :: anrm, anrmto, bignum, bnrm, bnrmto, eps, pl, pr, smlnum
           ! Local Arrays 
           real(${ck}$) :: dif(2_${ik}$)
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode the input arguments
           if( stdlib_lsame( jobvsl, 'N' ) ) then
              ijobvl = 1_${ik}$
              ilvsl = .false.
           else if( stdlib_lsame( jobvsl, 'V' ) ) then
              ijobvl = 2_${ik}$
              ilvsl = .true.
           else
              ijobvl = -1_${ik}$
              ilvsl = .false.
           end if
           if( stdlib_lsame( jobvsr, 'N' ) ) then
              ijobvr = 1_${ik}$
              ilvsr = .false.
           else if( stdlib_lsame( jobvsr, 'V' ) ) then
              ijobvr = 2_${ik}$
              ilvsr = .true.
           else
              ijobvr = -1_${ik}$
              ilvsr = .false.
           end if
           wantst = stdlib_lsame( sort, 'S' )
           wantsn = stdlib_lsame( sense, 'N' )
           wantse = stdlib_lsame( sense, 'E' )
           wantsv = stdlib_lsame( sense, 'V' )
           wantsb = stdlib_lsame( sense, 'B' )
           lquery = ( lwork==-1_${ik}$ .or. liwork==-1_${ik}$ )
           if( wantsn ) then
              ijob = 0_${ik}$
           else if( wantse ) then
              ijob = 1_${ik}$
           else if( wantsv ) then
              ijob = 2_${ik}$
           else if( wantsb ) then
              ijob = 4_${ik}$
           end if
           ! test the input arguments
           info = 0_${ik}$
           if( ijobvl<=0_${ik}$ ) then
              info = -1_${ik}$
           else if( ijobvr<=0_${ik}$ ) then
              info = -2_${ik}$
           else if( ( .not.wantst ) .and. ( .not.stdlib_lsame( sort, 'N' ) ) ) then
              info = -3_${ik}$
           else if( .not.( wantsn .or. wantse .or. wantsv .or. wantsb ) .or.( .not.wantst .and. &
                     .not.wantsn ) ) then
              info = -5_${ik}$
           else if( n<0_${ik}$ ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -8_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -10_${ik}$
           else if( ldvsl<1_${ik}$ .or. ( ilvsl .and. ldvsl<n ) ) then
              info = -15_${ik}$
           else if( ldvsr<1_${ik}$ .or. ( ilvsr .and. ldvsr<n ) ) then
              info = -17_${ik}$
           end if
           ! compute workspace
            ! (note: comments in the code beginning "workspace:" describe the
             ! minimal amount of workspace needed at that point in the code,
             ! as well as the preferred amount for good performance.
             ! nb refers to the optimal block size for the immediately
             ! following subroutine, as returned by stdlib${ii}$_ilaenv.)
           if( info==0_${ik}$ ) then
              if( n>0_${ik}$) then
                 minwrk = 2_${ik}$*n
                 maxwrk = n*(1_${ik}$ + stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, 1_${ik}$, n, 0_${ik}$ ) )
                 maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) )
                           
                 if( ilvsl ) then
                    maxwrk = max( maxwrk, n*( 1_${ik}$ +stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', n, 1_${ik}$, n, -1_${ik}$ ) ) &
                              )
                 end if
                 lwrk = maxwrk
                 if( ijob>=1_${ik}$ )lwrk = max( lwrk, n*n/2_${ik}$ )
              else
                 minwrk = 1_${ik}$
                 maxwrk = 1_${ik}$
                 lwrk   = 1_${ik}$
              end if
              work( 1_${ik}$ ) = lwrk
              if( wantsn .or. n==0_${ik}$ ) then
                 liwmin = 1_${ik}$
              else
                 liwmin = n + 2_${ik}$
              end if
              iwork( 1_${ik}$ ) = liwmin
              if( lwork<minwrk .and. .not.lquery ) then
                 info = -21_${ik}$
              else if( liwork<liwmin  .and. .not.lquery) then
                 info = -24_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGESX', -info )
              return
           else if (lquery) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              sdim = 0_${ik}$
              return
           end if
           ! get machine constants
           eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           smlnum = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' )
           bignum = one / smlnum
           call stdlib${ii}$_${c2ri(ci)}$labad( smlnum, bignum )
           smlnum = sqrt( smlnum ) / eps
           bignum = one / smlnum
           ! scale a if max element outside range [smlnum,bignum]
           anrm = stdlib${ii}$_${ci}$lange( 'M', n, n, a, lda, rwork )
           ilascl = .false.
           if( anrm>zero .and. anrm<smlnum ) then
              anrmto = smlnum
              ilascl = .true.
           else if( anrm>bignum ) then
              anrmto = bignum
              ilascl = .true.
           end if
           if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrm, anrmto, n, n, a, lda, ierr )
           ! scale b if max element outside range [smlnum,bignum]
           bnrm = stdlib${ii}$_${ci}$lange( 'M', n, n, b, ldb, rwork )
           ilbscl = .false.
           if( bnrm>zero .and. bnrm<smlnum ) then
              bnrmto = smlnum
              ilbscl = .true.
           else if( bnrm>bignum ) then
              bnrmto = bignum
              ilbscl = .true.
           end if
           if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrm, bnrmto, n, n, b, ldb, ierr )
           ! permute the matrix to make it more nearly triangular
           ! (real workspace: need 6*n)
           ileft = 1_${ik}$
           iright = n + 1_${ik}$
           irwrk = iright + n
           call stdlib${ii}$_${ci}$ggbal( 'P', n, a, lda, b, ldb, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     rwork( irwrk ), ierr )
           ! reduce b to triangular form (qr decomposition of b)
           ! (complex workspace: need n, prefer n*nb)
           irows = ihi + 1_${ik}$ - ilo
           icols = n + 1_${ik}$ - ilo
           itau = 1_${ik}$
           iwrk = itau + irows
           call stdlib${ii}$_${ci}$geqrf( irows, icols, b( ilo, ilo ), ldb, work( itau ),work( iwrk ), lwork+&
                     1_${ik}$-iwrk, ierr )
           ! apply the unitary transformation to matrix a
           ! (complex workspace: need n, prefer n*nb)
           call stdlib${ii}$_${ci}$unmqr( 'L', 'C', irows, icols, irows, b( ilo, ilo ), ldb,work( itau ), a( &
                     ilo, ilo ), lda, work( iwrk ),lwork+1-iwrk, ierr )
           ! initialize vsl
           ! (complex workspace: need n, prefer n*nb)
           if( ilvsl ) then
              call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsl, ldvsl )
              if( irows>1_${ik}$ ) then
                 call stdlib${ii}$_${ci}$lacpy( 'L', irows-1, irows-1, b( ilo+1, ilo ), ldb,vsl( ilo+1, ilo )&
                           , ldvsl )
              end if
              call stdlib${ii}$_${ci}$ungqr( irows, irows, irows, vsl( ilo, ilo ), ldvsl,work( itau ), work( &
                        iwrk ), lwork+1-iwrk, ierr )
           end if
           ! initialize vsr
           if( ilvsr )call stdlib${ii}$_${ci}$laset( 'FULL', n, n, czero, cone, vsr, ldvsr )
           ! reduce to generalized hessenberg form
           ! (workspace: none needed)
           call stdlib${ii}$_${ci}$gghrd( jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb, vsl,ldvsl, vsr, ldvsr,&
                      ierr )
           sdim = 0_${ik}$
           ! perform qz algorithm, computing schur vectors if desired
           ! (complex workspace: need n)
           ! (real workspace:    need n)
           iwrk = itau
           call stdlib${ii}$_${ci}$hgeqz( 'S', jobvsl, jobvsr, n, ilo, ihi, a, lda, b, ldb,alpha, beta, vsl, &
                     ldvsl, vsr, ldvsr, work( iwrk ),lwork+1-iwrk, rwork( irwrk ), ierr )
           if( ierr/=0_${ik}$ ) then
              if( ierr>0_${ik}$ .and. ierr<=n ) then
                 info = ierr
              else if( ierr>n .and. ierr<=2_${ik}$*n ) then
                 info = ierr - n
              else
                 info = n + 1_${ik}$
              end if
              go to 40
           end if
           ! sort eigenvalues alpha/beta and compute the reciprocal of
           ! condition number(s)
           if( wantst ) then
              ! undo scaling on eigenvalues before selctging
              if( ilascl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
                        
              if( ilbscl )call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
                        
              ! select eigenvalues
              do i = 1, n
                 bwork( i ) = selctg( alpha( i ), beta( i ) )
              end do
              ! reorder eigenvalues, transform generalized schur vectors, and
              ! compute reciprocal condition numbers
              ! (complex workspace: if ijob >= 1, need max(1, 2*sdim*(n-sdim))
                                  ! otherwise, need 1 )
              call stdlib${ii}$_${ci}$tgsen( ijob, ilvsl, ilvsr, bwork, n, a, lda, b, ldb,alpha, beta, vsl, &
              ldvsl, vsr, ldvsr, sdim, pl, pr,dif, work( iwrk ), lwork-iwrk+1, iwork, liwork,ierr &
                        )
              if( ijob>=1_${ik}$ )maxwrk = max( maxwrk, 2_${ik}$*sdim*( n-sdim ) )
              if( ierr==-21_${ik}$ ) then
                  ! not enough complex workspace
                 info = -21_${ik}$
              else
                 if( ijob==1_${ik}$ .or. ijob==4_${ik}$ ) then
                    rconde( 1_${ik}$ ) = pl
                    rconde( 2_${ik}$ ) = pr
                 end if
                 if( ijob==2_${ik}$ .or. ijob==4_${ik}$ ) then
                    rcondv( 1_${ik}$ ) = dif( 1_${ik}$ )
                    rcondv( 2_${ik}$ ) = dif( 2_${ik}$ )
                 end if
                 if( ierr==1_${ik}$ )info = n + 3_${ik}$
              end if
           end if
           ! apply permutation to vsl and vsr
           ! (workspace: none needed)
           if( ilvsl )call stdlib${ii}$_${ci}$ggbak( 'P', 'L', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsl, ldvsl, ierr )
           if( ilvsr )call stdlib${ii}$_${ci}$ggbak( 'P', 'R', n, ilo, ihi, rwork( ileft ),rwork( iright ), &
                     n, vsr, ldvsr, ierr )
           ! undo scaling
           if( ilascl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, n, a, lda, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, anrmto, anrm, n, 1_${ik}$, alpha, n, ierr )
           end if
           if( ilbscl ) then
              call stdlib${ii}$_${ci}$lascl( 'U', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, n, b, ldb, ierr )
              call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, bnrmto, bnrm, n, 1_${ik}$, beta, n, ierr )
           end if
           if( wantst ) then
              ! check if reordering is correct
              lastsl = .true.
              sdim = 0_${ik}$
              do i = 1, n
                 cursl = selctg( alpha( i ), beta( i ) )
                 if( cursl )sdim = sdim + 1_${ik}$
                 if( cursl .and. .not.lastsl )info = n + 2_${ik}$
                 lastsl = cursl
              end do
           end if
           40 continue
           work( 1_${ik}$ ) = maxwrk
           iwork( 1_${ik}$ ) = liwmin
           return
     end subroutine stdlib${ii}$_${ci}$ggesx

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgebal( job, n, a, lda, ilo, ihi, scale, info )
     !! SGEBAL balances a general real matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: scale(*)
        ! =====================================================================
           ! Parameters 
           real(sp), parameter :: sclfac = 2.0e+0_sp
           real(sp), parameter :: factor = 0.95e+0_sp
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(sp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_sswap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_sswap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( a( j, i )/=zero )cycle loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( a( i, j )/=zero )cycle loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_snrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_snrm2( l-k+1, a( i, k ), lda )
              ica = stdlib${ii}$_isamax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_isamax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
                 if( stdlib${ii}$_sisnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'SGEBAL', -info )
                 return
              end if
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_sscal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_sscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_sgebal

     pure module subroutine stdlib${ii}$_dgebal( job, n, a, lda, ilo, ihi, scale, info )
     !! DGEBAL balances a general real matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: scale(*)
        ! =====================================================================
           ! Parameters 
           real(dp), parameter :: sclfac = 2.0e+0_dp
           real(dp), parameter :: factor = 0.95e+0_dp
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(dp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_dswap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_dswap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( a( j, i )/=zero )cycle loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( a( i, j )/=zero )cycle loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_dnrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_dnrm2( l-k+1, a( i, k ), lda )
              ica = stdlib${ii}$_idamax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_idamax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
                 if( stdlib${ii}$_disnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'DGEBAL', -info )
                 return
              end if
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_dscal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_dscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_dgebal

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gebal( job, n, a, lda, ilo, ihi, scale, info )
     !! DGEBAL: balances a general real matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: scale(*)
        ! =====================================================================
           ! Parameters 
           real(${rk}$), parameter :: sclfac = 2.0e+0_${rk}$
           real(${rk}$), parameter :: factor = 0.95e+0_${rk}$
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(${rk}$) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_${ri}$swap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_${ri}$swap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( a( j, i )/=zero )cycle loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( a( i, j )/=zero )cycle loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_${ri}$lamch( 'S' ) / stdlib${ii}$_${ri}$lamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_${ri}$nrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_${ri}$nrm2( l-k+1, a( i, k ), lda )
              ica = stdlib${ii}$_i${ri}$amax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_i${ri}$amax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
                 if( stdlib${ii}$_${ri}$isnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'DGEBAL', -info )
                 return
              end if
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_${ri}$scal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_${ri}$scal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_${ri}$gebal

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgebal( job, n, a, lda, ilo, ihi, scale, info )
     !! CGEBAL balances a general complex matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(sp), intent(out) :: scale(*)
           complex(sp), intent(inout) :: a(lda,*)
        ! =====================================================================
           ! Parameters 
           real(sp), parameter :: sclfac = 2.0e+0_sp
           real(sp), parameter :: factor = 0.95e+0_sp
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(sp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_cswap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_cswap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( real( a( j, i ),KIND=sp)/=zero .or. aimag( a( j, i ) )/=zero )cycle &
                           loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( real( a( i, j ),KIND=sp)/=zero .or. aimag( a( i, j ) )/=zero )cycle &
                           loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_slamch( 'S' ) / stdlib${ii}$_slamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_scnrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_scnrm2( l-k+1, a( i , k ), lda )
              ica = stdlib${ii}$_icamax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_icamax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
                 if( stdlib${ii}$_sisnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'CGEBAL', -info )
                 return
              end if
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_csscal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_csscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_cgebal

     pure module subroutine stdlib${ii}$_zgebal( job, n, a, lda, ilo, ihi, scale, info )
     !! ZGEBAL balances a general complex matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(dp), intent(out) :: scale(*)
           complex(dp), intent(inout) :: a(lda,*)
        ! =====================================================================
           ! Parameters 
           real(dp), parameter :: sclfac = 2.0e+0_dp
           real(dp), parameter :: factor = 0.95e+0_dp
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(dp) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_zswap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_zswap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( real( a( j, i ),KIND=dp)/=zero .or. aimag( a( j, i ) )/=zero )cycle &
                           loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( real( a( i, j ),KIND=dp)/=zero .or. aimag( a( i, j ) )/=zero )cycle &
                           loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_dlamch( 'S' ) / stdlib${ii}$_dlamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_dznrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_dznrm2( l-k+1, a( i, k ), lda )
              ica = stdlib${ii}$_izamax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_izamax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
                 if( stdlib${ii}$_disnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'ZGEBAL', -info )
                 return
              end if
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_zdscal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_zdscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_zgebal

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gebal( job, n, a, lda, ilo, ihi, scale, info )
     !! ZGEBAL: balances a general complex matrix A.  This involves, first,
     !! permuting A by a similarity transformation to isolate eigenvalues
     !! in the first 1 to ILO-1 and last IHI+1 to N elements on the
     !! diagonal; and second, applying a diagonal similarity transformation
     !! to rows and columns ILO to IHI to make the rows and columns as
     !! close in norm as possible.  Both steps are optional.
     !! Balancing may reduce the 1-norm of the matrix, and improve the
     !! accuracy of the computed eigenvalues and/or eigenvectors.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job
           integer(${ik}$), intent(out) :: ihi, ilo, info
           integer(${ik}$), intent(in) :: lda, n
           ! Array Arguments 
           real(${ck}$), intent(out) :: scale(*)
           complex(${ck}$), intent(inout) :: a(lda,*)
        ! =====================================================================
           ! Parameters 
           real(${ck}$), parameter :: sclfac = 2.0e+0_${ck}$
           real(${ck}$), parameter :: factor = 0.95e+0_${ck}$
           
           
           
           ! Local Scalars 
           logical(lk) :: noconv
           integer(${ik}$) :: i, ica, iexc, ira, j, k, l, m
           real(${ck}$) :: c, ca, f, g, r, ra, s, sfmax1, sfmax2, sfmin1, sfmin2
           ! Intrinsic Functions 
           ! test the input parameters
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEBAL', -info )
              return
           end if
           k = 1_${ik}$
           l = n
           if( n==0 )go to 210
           if( stdlib_lsame( job, 'N' ) ) then
              do i = 1, n
                 scale( i ) = one
              end do
              go to 210
           end if
           if( stdlib_lsame( job, 'S' ) )go to 120
           ! permutation to isolate eigenvalues if possible
           go to 50
           ! row and column exchange.
           20 continue
           scale( m ) = j
           if( j==m )go to 30
           call stdlib${ii}$_${ci}$swap( l, a( 1_${ik}$, j ), 1_${ik}$, a( 1_${ik}$, m ), 1_${ik}$ )
           call stdlib${ii}$_${ci}$swap( n-k+1, a( j, k ), lda, a( m, k ), lda )
           30 continue
           go to ( 40, 80 )iexc
           ! search for rows isolating an eigenvalue and push them down.
           40 continue
           if( l==1 )go to 210
           l = l - 1_${ik}$
           50 continue
           loop_70: do j = l, 1, -1
              loop_60: do i = 1, l
                 if( i==j )cycle loop_60
                 if( real( a( j, i ),KIND=${ck}$)/=zero .or. aimag( a( j, i ) )/=zero )cycle &
                           loop_70
              end do loop_60
              m = l
              iexc = 1_${ik}$
              go to 20
           end do loop_70
           go to 90
           ! search for columns isolating an eigenvalue and push them left.
           80 continue
           k = k + 1_${ik}$
           90 continue
           loop_110: do j = k, l
              loop_100: do i = k, l
                 if( i==j )cycle loop_100
                 if( real( a( i, j ),KIND=${ck}$)/=zero .or. aimag( a( i, j ) )/=zero )cycle &
                           loop_110
              end do loop_100
              m = k
              iexc = 2_${ik}$
              go to 20
           end do loop_110
           120 continue
           do i = k, l
              scale( i ) = one
           end do
           if( stdlib_lsame( job, 'P' ) )go to 210
           ! balance the submatrix in rows k to l.
           ! iterative loop for norm reduction
           sfmin1 = stdlib${ii}$_${c2ri(ci)}$lamch( 'S' ) / stdlib${ii}$_${c2ri(ci)}$lamch( 'P' )
           sfmax1 = one / sfmin1
           sfmin2 = sfmin1*sclfac
           sfmax2 = one / sfmin2
           140 continue
           noconv = .false.
           loop_200: do i = k, l
              c = stdlib${ii}$_${c2ri(ci)}$znrm2( l-k+1, a( k, i ), 1_${ik}$ )
              r = stdlib${ii}$_${c2ri(ci)}$znrm2( l-k+1, a( i, k ), lda )
              ica = stdlib${ii}$_i${ci}$amax( l, a( 1_${ik}$, i ), 1_${ik}$ )
              ca = abs( a( ica, i ) )
              ira = stdlib${ii}$_i${ci}$amax( n-k+1, a( i, k ), lda )
              ra = abs( a( i, ira+k-1 ) )
              ! guard against zero c or r due to underflow.
              if( c==zero .or. r==zero )cycle loop_200
              g = r / sclfac
              f = one
              s = c + r
              160 continue
              if( c>=g .or. max( f, c, ca )>=sfmax2 .or.min( r, g, ra )<=sfmin2 )go to 170
                 if( stdlib${ii}$_${c2ri(ci)}$isnan( c+f+ca+r+g+ra ) ) then
                 ! exit if nan to avoid infinite loop
                 info = -3_${ik}$
                 call stdlib${ii}$_xerbla( 'ZGEBAL', -info )
                 return
              end if
              f = f*sclfac
              c = c*sclfac
              ca = ca*sclfac
              r = r / sclfac
              g = g / sclfac
              ra = ra / sclfac
              go to 160
              170 continue
              g = c / sclfac
              180 continue
              if( g<r .or. max( r, ra )>=sfmax2 .or.min( f, c, g, ca )<=sfmin2 )go to 190
              f = f / sclfac
              c = c / sclfac
              g = g / sclfac
              ca = ca / sclfac
              r = r*sclfac
              ra = ra*sclfac
              go to 180
              ! now balance.
              190 continue
              if( ( c+r )>=factor*s )cycle loop_200
              if( f<one .and. scale( i )<one ) then
                 if( f*scale( i )<=sfmin1 )cycle loop_200
              end if
              if( f>one .and. scale( i )>one ) then
                 if( scale( i )>=sfmax1 / f )cycle loop_200
              end if
              g = one / f
              scale( i ) = scale( i )*f
              noconv = .true.
              call stdlib${ii}$_${ci}$dscal( n-k+1, g, a( i, k ), lda )
              call stdlib${ii}$_${ci}$dscal( l, f, a( 1_${ik}$, i ), 1_${ik}$ )
           end do loop_200
           if( noconv )go to 140
           210 continue
           ilo = k
           ihi = l
           return
     end subroutine stdlib${ii}$_${ci}$gebal

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! SGEHRD reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           real(sp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to zero
           do i = 1, ilo - 1
              tau( i ) = zero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = zero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'SGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'SGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin + tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**t
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_slahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**t. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = one
                 call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, &
                           ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )&
                           , lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_saxpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_slarfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, &
                           ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_sgehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_sgehrd

     pure module subroutine stdlib${ii}$_dgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! DGEHRD reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           real(dp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to zero
           do i = 1, ilo - 1
              tau( i ) = zero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = zero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'DGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin + tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**t
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_dlahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**t. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = one
                 call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, &
                           ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )&
                           , lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_daxpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_dlarfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, &
                           ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_dgehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_dgehrd

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! DGEHRD: reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           real(${rk}$) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to zero
           do i = 1, ilo - 1
              tau( i ) = zero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = zero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'DGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'DGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin + tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**t
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_${ri}$lahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**t. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = one
                 call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'TRANSPOSE',ihi, ihi-i-ib+1,ib, -one, work, &
                           ldwork, a( i+ib, i ), lda, one,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'TRANSPOSE','UNIT', i, ib-1,one, a( i+1, i )&
                           , lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_${ri}$axpy( i, -one, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_${ri}$larfb( 'LEFT', 'TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, n-i-ib+1, &
                           ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_${ri}$gehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ri}$gehrd

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! CGEHRD reduces a complex general matrix A to upper Hessenberg form H by
     !! an unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           complex(sp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to czero
           do i = 1, ilo - 1
              tau( i ) = czero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = czero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'CGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'CGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin+tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**h
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_clahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**h. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = cone
                 call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -&
                           cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, &
                           a( i+1, i ), lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_caxpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_clarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, &
                 n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, &
                           ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_cgehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_cgehrd

     pure module subroutine stdlib${ii}$_zgehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! ZGEHRD reduces a complex general matrix A to upper Hessenberg form H by
     !! an unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           complex(dp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           endif
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to czero
           do i = 1, ilo - 1
              tau( i ) = czero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = czero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin + tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**h
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_zlahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**h. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = cone
                 call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -&
                           cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, &
                           a( i+1, i ), lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_zaxpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_zlarfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, &
                 n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, &
                           ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_zgehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_zgehrd

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gehrd( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! ZGEHRD: reduces a complex general matrix A to upper Hessenberg form H by
     !! an unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Parameters 
           integer(${ik}$), parameter :: nbmax = 64_${ik}$
           integer(${ik}$), parameter :: ldt = nbmax+1
           integer(${ik}$), parameter :: tsize = ldt*nbmax
           
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iwt, j, ldwork, lwkopt, nb, nbmin, nh, nx
           complex(${ck}$) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, n ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              ! compute the workspace requirements
              nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              lwkopt = n*nb + tsize
              work( 1_${ik}$ ) = lwkopt
           endif
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEHRD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! set elements 1:ilo-1 and ihi:n-1 of tau to czero
           do i = 1, ilo - 1
              tau( i ) = czero
           end do
           do i = max( 1, ihi ), n - 1
              tau( i ) = czero
           end do
           ! quick return if possible
           nh = ihi - ilo + 1_${ik}$
           if( nh<=1_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! determine the block size
           nb = min( nbmax, stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
           nbmin = 2_${ik}$
           if( nb>1_${ik}$ .and. nb<nh ) then
              ! determine when to cross over from blocked to unblocked code
              ! (last block is always handled by unblocked code)
              nx = max( nb, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi, -1_${ik}$ ) )
              if( nx<nh ) then
                 ! determine if workspace is large enough for blocked code
                 if( lwork<n*nb+tsize ) then
                    ! not enough workspace to use optimal nb:  determine the
                    ! minimum value of nb, and reduce nb or force use of
                    ! unblocked code
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGEHRD', ' ', n, ilo, ihi,-1_${ik}$ ) )
                    if( lwork>=(n*nbmin + tsize) ) then
                       nb = (lwork-tsize) / n
                    else
                       nb = 1_${ik}$
                    end if
                 end if
              end if
           end if
           ldwork = n
           if( nb<nbmin .or. nb>=nh ) then
              ! use unblocked code below
              i = ilo
           else
              ! use blocked code
              iwt = 1_${ik}$ + n*nb
              do i = ilo, ihi - 1 - nx, nb
                 ib = min( nb, ihi-i )
                 ! reduce columns i:i+ib-1 to hessenberg form, returning the
                 ! matrices v and t of the block reflector h = i - v*t*v**h
                 ! which performs the reduction, and also the matrix y = a*v*t
                 call stdlib${ii}$_${ci}$lahr2( ihi, i, ib, a( 1_${ik}$, i ), lda, tau( i ),work( iwt ), ldt, work, &
                           ldwork )
                 ! apply the block reflector h to a(1:ihi,i+ib:ihi) from the
                 ! right, computing  a := a - y * v**h. v(i+ib,ib-1) must be set
                 ! to 1
                 ei = a( i+ib, i+ib-1 )
                 a( i+ib, i+ib-1 ) = cone
                 call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'CONJUGATE TRANSPOSE',ihi, ihi-i-ib+1,ib, -&
                           cone, work, ldwork, a( i+ib, i ), lda, cone,a( 1_${ik}$, i+ib ), lda )
                 a( i+ib, i+ib-1 ) = ei
                 ! apply the block reflector h to a(1:i,i+1:i+ib-1) from the
                 ! right
                 call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'CONJUGATE TRANSPOSE','UNIT', i, ib-1,cone, &
                           a( i+1, i ), lda, work, ldwork )
                 do j = 0, ib-2
                    call stdlib${ii}$_${ci}$axpy( i, -cone, work( ldwork*j+1 ), 1_${ik}$,a( 1_${ik}$, i+j+1 ), 1_${ik}$ )
                 end do
                 ! apply the block reflector h to a(i+1:ihi,i+ib:n) from the
                 ! left
                 call stdlib${ii}$_${ci}$larfb( 'LEFT', 'CONJUGATE TRANSPOSE', 'FORWARD','COLUMNWISE',ihi-i, &
                 n-i-ib+1, ib, a( i+1, i ), lda,work( iwt ), ldt, a( i+1, i+ib ), lda,work, &
                           ldwork )
              end do
           end if
           ! use unblocked code to reduce the rest of the matrix
           call stdlib${ii}$_${ci}$gehd2( n, i, ihi, a, lda, tau, work, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ci}$gehrd

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! SGEHD2 reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(sp) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              call stdlib${ii}$_slarfg( ihi-i, a( i+1, i ), a( min( i+2, n ), i ), 1_${ik}$,tau( i ) )
              aii = a( i+1, i )
              a( i+1, i ) = one
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_slarf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i) to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_slarf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$, tau( i ),a( i+1, i+1 ), lda, &
                        work )
              a( i+1, i ) = aii
           end do
           return
     end subroutine stdlib${ii}$_sgehd2

     pure module subroutine stdlib${ii}$_dgehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! DGEHD2 reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(dp) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              call stdlib${ii}$_dlarfg( ihi-i, a( i+1, i ), a( min( i+2, n ), i ), 1_${ik}$,tau( i ) )
              aii = a( i+1, i )
              a( i+1, i ) = one
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_dlarf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i) to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_dlarf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$, tau( i ),a( i+1, i+1 ), lda, &
                        work )
              a( i+1, i ) = aii
           end do
           return
     end subroutine stdlib${ii}$_dgehd2

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! DGEHD2: reduces a real general matrix A to upper Hessenberg form H by
     !! an orthogonal similarity transformation:  Q**T * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(${rk}$) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              call stdlib${ii}$_${ri}$larfg( ihi-i, a( i+1, i ), a( min( i+2, n ), i ), 1_${ik}$,tau( i ) )
              aii = a( i+1, i )
              a( i+1, i ) = one
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_${ri}$larf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i) to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_${ri}$larf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$, tau( i ),a( i+1, i+1 ), lda, &
                        work )
              a( i+1, i ) = aii
           end do
           return
     end subroutine stdlib${ii}$_${ri}$gehd2

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! CGEHD2 reduces a complex general matrix A to upper Hessenberg form H
     !! by a unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(sp) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              alpha = a( i+1, i )
              call stdlib${ii}$_clarfg( ihi-i, alpha, a( min( i+2, n ), i ), 1_${ik}$, tau( i ) )
              a( i+1, i ) = cone
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_clarf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i)**h to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_clarf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$,conjg( tau( i ) ), a( i+1, i+&
                        1_${ik}$ ), lda, work )
              a( i+1, i ) = alpha
           end do
           return
     end subroutine stdlib${ii}$_cgehd2

     pure module subroutine stdlib${ii}$_zgehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! ZGEHD2 reduces a complex general matrix A to upper Hessenberg form H
     !! by a unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(dp) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              alpha = a( i+1, i )
              call stdlib${ii}$_zlarfg( ihi-i, alpha, a( min( i+2, n ), i ), 1_${ik}$, tau( i ) )
              a( i+1, i ) = cone
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_zlarf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i)**h to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_zlarf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$,conjg( tau( i ) ), a( i+1, i+&
                        1_${ik}$ ), lda, work )
              a( i+1, i ) = alpha
           end do
           return
     end subroutine stdlib${ii}$_zgehd2

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gehd2( n, ilo, ihi, a, lda, tau, work, info )
     !! ZGEHD2: reduces a complex general matrix A to upper Hessenberg form H
     !! by a unitary similarity transformation:  Q**H * A * Q = H .
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(${ck}$) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEHD2', -info )
              return
           end if
           do i = ilo, ihi - 1
              ! compute elementary reflector h(i) to annihilate a(i+2:ihi,i)
              alpha = a( i+1, i )
              call stdlib${ii}$_${ci}$larfg( ihi-i, alpha, a( min( i+2, n ), i ), 1_${ik}$, tau( i ) )
              a( i+1, i ) = cone
              ! apply h(i) to a(1:ihi,i+1:ihi) from the right
              call stdlib${ii}$_${ci}$larf( 'RIGHT', ihi, ihi-i, a( i+1, i ), 1_${ik}$, tau( i ),a( 1_${ik}$, i+1 ), lda, &
                        work )
              ! apply h(i)**h to a(i+1:ihi,i+1:n) from the left
              call stdlib${ii}$_${ci}$larf( 'LEFT', ihi-i, n-i, a( i+1, i ), 1_${ik}$,conjg( tau( i ) ), a( i+1, i+&
                        1_${ik}$ ), lda, work )
              a( i+1, i ) = alpha
           end do
           return
     end subroutine stdlib${ii}$_${ci}$gehd2

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! SGEBAK forms the right or left eigenvectors of a real general matrix
     !! by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by SGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(inout) :: v(ldv,*)
           real(sp), intent(in) :: scale(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(sp) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_sscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_sscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_sswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_sswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_sgebak

     pure module subroutine stdlib${ii}$_dgebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! DGEBAK forms the right or left eigenvectors of a real general matrix
     !! by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by DGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(in) :: scale(*)
           real(dp), intent(inout) :: v(ldv,*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(dp) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_dscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_dscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_dswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_dswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_dgebak

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! DGEBAK: forms the right or left eigenvectors of a real general matrix
     !! by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by DGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(in) :: scale(*)
           real(${rk}$), intent(inout) :: v(ldv,*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(${rk}$) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_${ri}$scal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_${ri}$scal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_${ri}$swap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_${ri}$swap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_${ri}$gebak

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! CGEBAK forms the right or left eigenvectors of a complex general
     !! matrix by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by CGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(in) :: scale(*)
           complex(sp), intent(inout) :: v(ldv,*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(sp) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_csscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_csscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_cswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_cswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_cgebak

     pure module subroutine stdlib${ii}$_zgebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! ZGEBAK forms the right or left eigenvectors of a complex general
     !! matrix by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by ZGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(in) :: scale(*)
           complex(dp), intent(inout) :: v(ldv,*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(dp) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_zdscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_zdscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_zswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_zswap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_zgebak

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gebak( job, side, n, ilo, ihi, scale, m, v, ldv,info )
     !! ZGEBAK: forms the right or left eigenvectors of a complex general
     !! matrix by backward transformation on the computed eigenvectors of the
     !! balanced matrix output by ZGEBAL.
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: job, side
           integer(${ik}$), intent(in) :: ihi, ilo, ldv, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${ck}$), intent(in) :: scale(*)
           complex(${ck}$), intent(inout) :: v(ldv,*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: leftv, rightv
           integer(${ik}$) :: i, ii, k
           real(${ck}$) :: s
           ! Intrinsic Functions 
           ! Executable Statements 
           ! decode and test the input parameters
           rightv = stdlib_lsame( side, 'R' )
           leftv = stdlib_lsame( side, 'L' )
           info = 0_${ik}$
           if( .not.stdlib_lsame( job, 'N' ) .and. .not.stdlib_lsame( job, 'P' ) &
                     .and..not.stdlib_lsame( job, 'S' ) .and. .not.stdlib_lsame( job, 'B' ) ) then
              info = -1_${ik}$
           else if( .not.rightv .and. .not.leftv ) then
              info = -2_${ik}$
           else if( n<0_${ik}$ ) then
              info = -3_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -4_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -5_${ik}$
           else if( m<0_${ik}$ ) then
              info = -7_${ik}$
           else if( ldv<max( 1_${ik}$, n ) ) then
              info = -9_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGEBAK', -info )
              return
           end if
           ! quick return if possible
           if( n==0 )return
           if( m==0 )return
           if( stdlib_lsame( job, 'N' ) )return
           if( ilo==ihi )go to 30
           ! backward balance
           if( stdlib_lsame( job, 'S' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 do i = ilo, ihi
                    s = scale( i )
                    call stdlib${ii}$_${ci}$dscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
              if( leftv ) then
                 do i = ilo, ihi
                    s = one / scale( i )
                    call stdlib${ii}$_${ci}$dscal( m, s, v( i, 1_${ik}$ ), ldv )
                 end do
              end if
           end if
           ! backward permutation
           ! for  i = ilo-1 step -1 until 1,
                    ! ihi+1 step 1 until n do --
                    30 continue
           if( stdlib_lsame( job, 'P' ) .or. stdlib_lsame( job, 'B' ) ) then
              if( rightv ) then
                 loop_40: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_40
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_40
                    call stdlib${ii}$_${ci}$swap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_40
              end if
              if( leftv ) then
                 loop_50: do ii = 1, n
                    i = ii
                    if( i>=ilo .and. i<=ihi )cycle loop_50
                    if( i<ilo )i = ilo - ii
                    k = scale( i )
                    if( k==i )cycle loop_50
                    call stdlib${ii}$_${ci}$swap( m, v( i, 1_${ik}$ ), ldv, v( k, 1_${ik}$ ), ldv )
                 end do loop_50
              end if
           end if
           return
     end subroutine stdlib${ii}$_${ci}$gebak

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_slahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! SLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an orthogonal similarity transformation
     !! Q**T * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by SGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(sp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**t
                 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, one, a( k+1, i ), 1_${ik}$ )
                 ! apply i - v * t**t * v**t to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**t * b1
                 call stdlib${ii}$_scopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_strmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),&
                            1_${ik}$ )
                 ! w := w + v2**t * b2
                 call stdlib${ii}$_sgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), &
                           1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**t * w
                 call stdlib${ii}$_strmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ )
                           
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )&
                           , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_strmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_saxpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_slarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = one
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),&
                         1_${ik}$, zero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_sgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, &
                        zero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        one, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_sscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_sscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_strmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_slacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_strmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_sgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, &
                     2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy )
           call stdlib${ii}$_strmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_slahr2

     pure module subroutine stdlib${ii}$_dlahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an orthogonal similarity transformation
     !! Q**T * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by DGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(dp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**t
                 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, one, a( k+1, i ), 1_${ik}$ )
                 ! apply i - v * t**t * v**t to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**t * b1
                 call stdlib${ii}$_dcopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_dtrmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),&
                            1_${ik}$ )
                 ! w := w + v2**t * b2
                 call stdlib${ii}$_dgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), &
                           1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**t * w
                 call stdlib${ii}$_dtrmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ )
                           
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )&
                           , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_dtrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_daxpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_dlarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = one
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),&
                         1_${ik}$, zero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_dgemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, &
                        zero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        one, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_dscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_dscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_dtrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_dlacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_dtrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_dgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, &
                     2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy )
           call stdlib${ii}$_dtrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_dlahr2

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$lahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! DLAHR2: reduces the first NB columns of A real general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an orthogonal similarity transformation
     !! Q**T * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by DGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(${rk}$) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**t
                 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, i-1, -one, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, one, a( k+1, i ), 1_${ik}$ )
                 ! apply i - v * t**t * v**t to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**t * b1
                 call stdlib${ii}$_${ri}$copy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$trmv( 'LOWER', 'TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, t( 1_${ik}$, nb ),&
                            1_${ik}$ )
                 ! w := w + v2**t * b2
                 call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ),lda, a( k+i, i ), &
                           1_${ik}$, one, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**t * w
                 call stdlib${ii}$_${ri}$trmv( 'UPPER', 'TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, nb ), 1_${ik}$ )
                           
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k-i+1, i-1, -one,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb )&
                           , 1_${ik}$, one, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_${ri}$trmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$axpy( i-1, -one, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_${ri}$larfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = one
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, n-k-i+1,one, a( k+1, i+1 ),lda, a( k+i, i ),&
                         1_${ik}$, zero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_${ri}$gemv( 'TRANSPOSE', n-k-i+1, i-1,one, a( k+i, 1_${ik}$ ), lda,a( k+i, i ), 1_${ik}$, &
                        zero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-k, i-1, -one,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        one, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_${ri}$scal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_${ri}$scal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_${ri}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_${ri}$lacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,one, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_${ri}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, one,a( 1_${ik}$, &
                     2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, one, y,ldy )
           call stdlib${ii}$_${ri}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,one, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_${ri}$lahr2

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_clahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! CLAHR2 reduces the first NB columns of A complex general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an unitary similarity transformation
     !! Q**H * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*v**H, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by CGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(sp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**h
                 call stdlib${ii}$_clacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, cone, a( k+1, i ), 1_${ik}$ )
                 call stdlib${ii}$_clacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 ! apply i - v * t**h * v**h to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**h * b1
                 call stdlib${ii}$_ccopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_ctrmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, &
                           t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := w + v2**h * b2
                 call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( &
                           k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**h * w
                 call stdlib${ii}$_ctrmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb &
                           ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_ctrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_caxpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_clarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = cone
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )&
                        , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_cgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+&
                        i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        cone, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_cscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_cscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_ctrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_clacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_ctrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_cgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,&
                      2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy )
           call stdlib${ii}$_ctrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_clahr2

     pure module subroutine stdlib${ii}$_zlahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! ZLAHR2 reduces the first NB columns of A complex general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an unitary similarity transformation
     !! Q**H * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*V**H, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by ZGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(dp) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**h
                 call stdlib${ii}$_zlacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, cone, a( k+1, i ), 1_${ik}$ )
                 call stdlib${ii}$_zlacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 ! apply i - v * t**h * v**h to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**h * b1
                 call stdlib${ii}$_zcopy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_ztrmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, &
                           t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := w + v2**h * b2
                 call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( &
                           k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**h * w
                 call stdlib${ii}$_ztrmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb &
                           ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_ztrmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_zaxpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_zlarfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = cone
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )&
                        , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_zgemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+&
                        i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        cone, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_zscal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_zscal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_ztrmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_zlacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_ztrmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_zgemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,&
                      2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy )
           call stdlib${ii}$_ztrmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_zlahr2

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$lahr2( n, k, nb, a, lda, tau, t, ldt, y, ldy )
     !! ZLAHR2: reduces the first NB columns of A complex general n-BY-(n-k+1)
     !! matrix A so that elements below the k-th subdiagonal are zero. The
     !! reduction is performed by an unitary similarity transformation
     !! Q**H * A * Q. The routine returns the matrices V and T which determine
     !! Q as a block reflector I - V*T*V**H, and also the matrix Y = A * V * T.
     !! This is an auxiliary routine called by ZGEHRD.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: k, lda, ldt, ldy, n, nb
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: t(ldt,nb), tau(nb), y(ldy,nb)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i
           complex(${ck}$) :: ei
           ! Intrinsic Functions 
           ! Executable Statements 
           ! quick return if possible
           if( n<=1 )return
           loop_10: do i = 1, nb
              if( i>1_${ik}$ ) then
                 ! update a(k+1:n,i)
                 ! update i-th column of a - y * v**h
                 call stdlib${ii}$_${ci}$lacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, i-1, -cone, y(k+1,1_${ik}$), ldy,a( k+i-1, 1_${ik}$ ), &
                           lda, cone, a( k+1, i ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$lacgv( i-1, a( k+i-1, 1_${ik}$ ), lda )
                 ! apply i - v * t**h * v**h to this column (call it b) from the
                 ! left, using the last column of t as workspace
                 ! let  v = ( v1 )   and   b = ( b1 )   (first i-1 rows)
                          ! ( v2 )             ( b2 )
                 ! where v1 is unit lower triangular
                 ! w := v1**h * b1
                 call stdlib${ii}$_${ci}$copy( i-1, a( k+1, i ), 1_${ik}$, t( 1_${ik}$, nb ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$trmv( 'LOWER', 'CONJUGATE TRANSPOSE', 'UNIT',i-1, a( k+1, 1_${ik}$ ),lda, &
                           t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := w + v2**h * b2
                 call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ),lda, a( &
                           k+i, i ), 1_${ik}$, cone, t( 1_${ik}$, nb ), 1_${ik}$ )
                 ! w := t**h * w
                 call stdlib${ii}$_${ci}$trmv( 'UPPER', 'CONJUGATE TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 ! b2 := b2 - v2*w
                 call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k-i+1, i-1, -cone,a( k+i, 1_${ik}$ ),lda, t( 1_${ik}$, nb &
                           ), 1_${ik}$, cone, a( k+i, i ), 1_${ik}$ )
                 ! b1 := b1 - v1*w
                 call stdlib${ii}$_${ci}$trmv( 'LOWER', 'NO TRANSPOSE','UNIT', i-1,a( k+1, 1_${ik}$ ), lda, t( 1_${ik}$, &
                           nb ), 1_${ik}$ )
                 call stdlib${ii}$_${ci}$axpy( i-1, -cone, t( 1_${ik}$, nb ), 1_${ik}$, a( k+1, i ), 1_${ik}$ )
                 a( k+i-1, i-1 ) = ei
              end if
              ! generate the elementary reflector h(i) to annihilate
              ! a(k+i+1:n,i)
              call stdlib${ii}$_${ci}$larfg( n-k-i+1, a( k+i, i ), a( min( k+i+1, n ), i ), 1_${ik}$,tau( i ) )
                        
              ei = a( k+i, i )
              a( k+i, i ) = cone
              ! compute  y(k+1:n,i)
              call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, n-k-i+1,cone, a( k+1, i+1 ),lda, a( k+i, i )&
                        , 1_${ik}$, czero, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_${ci}$gemv( 'CONJUGATE TRANSPOSE', n-k-i+1, i-1,cone, a( k+i, 1_${ik}$ ), lda,a( k+&
                        i, i ), 1_${ik}$, czero, t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-k, i-1, -cone,y( k+1, 1_${ik}$ ), ldy,t( 1_${ik}$, i ), 1_${ik}$, &
                        cone, y( k+1, i ), 1_${ik}$ )
              call stdlib${ii}$_${ci}$scal( n-k, tau( i ), y( k+1, i ), 1_${ik}$ )
              ! compute t(1:i,i)
              call stdlib${ii}$_${ci}$scal( i-1, -tau( i ), t( 1_${ik}$, i ), 1_${ik}$ )
              call stdlib${ii}$_${ci}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT',i-1, t, ldt,t( 1_${ik}$, i ), 1_${ik}$ )
                        
              t( i, i ) = tau( i )
           end do loop_10
           a( k+nb, nb ) = ei
           ! compute y(1:k,1:nb)
           call stdlib${ii}$_${ci}$lacpy( 'ALL', k, nb, a( 1_${ik}$, 2_${ik}$ ), lda, y, ldy )
           call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'LOWER', 'NO TRANSPOSE','UNIT', k, nb,cone, a( k+1, 1_${ik}$ ), &
                     lda, y, ldy )
           if( n>k+nb )call stdlib${ii}$_${ci}$gemm( 'NO TRANSPOSE', 'NO TRANSPOSE', k,nb, n-k-nb, cone,a( 1_${ik}$,&
                      2_${ik}$+nb ), lda, a( k+1+nb, 1_${ik}$ ), lda, cone, y,ldy )
           call stdlib${ii}$_${ci}$trmm( 'RIGHT', 'UPPER', 'NO TRANSPOSE','NON-UNIT', k, nb,cone, t, ldt, y, &
                     ldy )
           return
     end subroutine stdlib${ii}$_${ci}$lahr2

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_cunghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! CUNGHR generates a complex unitary matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! CGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(in) :: tau(*)
           complex(sp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CUNGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors cone
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = czero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = czero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_cungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_cunghr

     pure module subroutine stdlib${ii}$_zunghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! ZUNGHR generates a complex unitary matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! ZGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(in) :: tau(*)
           complex(dp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors cone
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = czero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = czero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_zungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_zunghr

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$unghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! ZUNGHR: generates a complex unitary matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! ZGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(in) :: tau(*)
           complex(${ck}$), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors cone
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = czero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = czero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = czero
              end do
              a( j, j ) = cone
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_${ci}$ungqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ci}$unghr

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_cunmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! CUNMHR overwrites the general complex M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'C':      Q**H * C       C * Q**H
     !! where Q is a complex unitary matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by CGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*), c(ldc,*)
           complex(sp), intent(in) :: tau(*)
           complex(sp), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'C' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CUNMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_cunmqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_cunmhr

     pure module subroutine stdlib${ii}$_zunmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! ZUNMHR overwrites the general complex M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'C':      Q**H * C       C * Q**H
     !! where Q is a complex unitary matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by ZGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*), c(ldc,*)
           complex(dp), intent(in) :: tau(*)
           complex(dp), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'C' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_zunmqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_zunmhr

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$unmhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! ZUNMHR: overwrites the general complex M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'C':      Q**H * C       C * Q**H
     !! where Q is a complex unitary matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by ZGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*), c(ldc,*)
           complex(${ck}$), intent(in) :: tau(*)
           complex(${ck}$), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'C' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_${ci}$unmqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ci}$unmhr

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sorghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! SORGHR generates a real orthogonal matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! SGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(in) :: tau(*)
           real(sp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors one
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = zero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = zero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_sorgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_sorghr

     pure module subroutine stdlib${ii}$_dorghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! DORGHR generates a real orthogonal matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! DGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(in) :: tau(*)
           real(dp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors one
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = zero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = zero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_dorgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_dorghr

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$orghr( n, ilo, ihi, a, lda, tau, work, lwork, info )
     !! DORGHR: generates a real orthogonal matrix Q which is defined as the
     !! product of IHI-ILO elementary reflectors of order N, as returned by
     !! DGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(in) :: ihi, ilo, lda, lwork, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(in) :: tau(*)
           real(${rk}$), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, iinfo, j, lwkopt, nb, nh
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, n ) ) then
              info = -2_${ik}$
           else if( ihi<min( ilo, n ) .or. ihi>n ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, nh ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
              nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORGQR', ' ', nh, nh, nh, -1_${ik}$ )
              lwkopt = max( 1_${ik}$, nh )*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORGHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           ! shift the vectors which define the elementary reflectors one
           ! column to the right, and set the first ilo and the last n-ihi
           ! rows and columns to those of the unit matrix
           do j = ihi, ilo + 1, -1
              do i = 1, j - 1
                 a( i, j ) = zero
              end do
              do i = j + 1, ihi
                 a( i, j ) = a( i, j-1 )
              end do
              do i = ihi + 1, n
                 a( i, j ) = zero
              end do
           end do
           do j = 1, ilo
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           do j = ihi + 1, n
              do i = 1, n
                 a( i, j ) = zero
              end do
              a( j, j ) = one
           end do
           if( nh>0_${ik}$ ) then
              ! generate q(ilo+1:ihi,ilo+1:ihi)
              call stdlib${ii}$_${ri}$orgqr( nh, nh, nh, a( ilo+1, ilo+1 ), lda, tau( ilo ),work, lwork, &
                        iinfo )
           end if
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ri}$orghr

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! SORMHR overwrites the general real M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'T':      Q**T * C       C * Q**T
     !! where Q is a real orthogonal matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by SGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*), c(ldc,*)
           real(sp), intent(in) :: tau(*)
           real(sp), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'T' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_sormqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_sormhr

     pure module subroutine stdlib${ii}$_dormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! DORMHR overwrites the general real M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'T':      Q**T * C       C * Q**T
     !! where Q is a real orthogonal matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by DGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*), c(ldc,*)
           real(dp), intent(in) :: tau(*)
           real(dp), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'T' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_dormqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_dormhr

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$ormhr( side, trans, m, n, ilo, ihi, a, lda, tau, c,ldc, work, lwork, &
     !! DORMHR: overwrites the general real M-by-N matrix C with
     !! SIDE = 'L'     SIDE = 'R'
     !! TRANS = 'N':      Q * C          C * Q
     !! TRANS = 'T':      Q**T * C       C * Q**T
     !! where Q is a real orthogonal matrix of order nq, with nq = m if
     !! SIDE = 'L' and nq = n if SIDE = 'R'. Q is defined as the product of
     !! IHI-ILO elementary reflectors, as returned by DGEHRD:
     !! Q = H(ilo) H(ilo+1) . . . H(ihi-1).
               info )
        ! -- lapack computational routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           character, intent(in) :: side, trans
           integer(${ik}$), intent(in) :: ihi, ilo, lda, ldc, lwork, m, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*), c(ldc,*)
           real(${rk}$), intent(in) :: tau(*)
           real(${rk}$), intent(out) :: work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, lquery
           integer(${ik}$) :: i1, i2, iinfo, lwkopt, mi, nb, nh, ni, nq, nw
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nh = ihi - ilo
           left = stdlib_lsame( side, 'L' )
           lquery = ( lwork==-1_${ik}$ )
           ! nq is the order of q and nw is the minimum dimension of work
           if( left ) then
              nq = m
              nw = max( 1_${ik}$, n )
           else
              nq = n
              nw = max( 1_${ik}$, m )
           end if
           if( .not.left .and. .not.stdlib_lsame( side, 'R' ) ) then
              info = -1_${ik}$
           else if( .not.stdlib_lsame( trans, 'N' ) .and. .not.stdlib_lsame( trans, 'T' ) )&
                     then
              info = -2_${ik}$
           else if( m<0_${ik}$ ) then
              info = -3_${ik}$
           else if( n<0_${ik}$ ) then
              info = -4_${ik}$
           else if( ilo<1_${ik}$ .or. ilo>max( 1_${ik}$, nq ) ) then
              info = -5_${ik}$
           else if( ihi<min( ilo, nq ) .or. ihi>nq ) then
              info = -6_${ik}$
           else if( lda<max( 1_${ik}$, nq ) ) then
              info = -8_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
              info = -11_${ik}$
           else if( lwork<nw .and. .not.lquery ) then
              info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
              if( left ) then
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', side // trans, nh, n, nh, -1_${ik}$ )
              else
                 nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', side // trans, m, nh, nh, -1_${ik}$ )
              end if
              lwkopt = nw*nb
              work( 1_${ik}$ ) = lwkopt
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORMHR', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m==0_${ik}$ .or. n==0_${ik}$ .or. nh==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           if( left ) then
              mi = nh
              ni = n
              i1 = ilo + 1_${ik}$
              i2 = 1_${ik}$
           else
              mi = m
              ni = nh
              i1 = 1_${ik}$
              i2 = ilo + 1_${ik}$
           end if
           call stdlib${ii}$_${ri}$ormqr( side, trans, mi, ni, nh, a( ilo+1, ilo ), lda,tau( ilo ), c( i1, &
                     i2 ), ldc, work, lwork, iinfo )
           work( 1_${ik}$ ) = lwkopt
           return
     end subroutine stdlib${ii}$_${ri}$ormhr

#:endif
#:endfor


#:endfor
end submodule stdlib_lapack_eigv_gen