stdlib_lapack_orthogonal_factors_ql.fypp Source File


Source Code

#:include "common.fypp" 
submodule(stdlib_lapack_orthogonal_factors) stdlib_lapack_orthogonal_factors_ql
  implicit none


  contains
#:for ik,it,ii in LINALG_INT_KINDS_TYPES

     pure module subroutine stdlib${ii}$_sgelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! SGELQ computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if ( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
               lminws = .true.
               mb = 1_${ik}$
               nb = n
             end if
             if( lwork<lwopt ) then
               lminws = .true.
               mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'SGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_sgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_slaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_sgelq

     pure module subroutine stdlib${ii}$_dgelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! DGELQ computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if ( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
                 lminws = .true.
                 mb = 1_${ik}$
                 nb = n
             end if
             if( lwork<lwopt ) then
                 lminws = .true.
                 mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'DGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_dgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_dlaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_dgelq

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! DGELQ: computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if ( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
                 lminws = .true.
                 mb = 1_${ik}$
                 nb = n
             end if
             if( lwork<lwopt ) then
                 lminws = .true.
                 mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'DGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_${ri}$gelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_${ri}$laswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_${ri}$gelq

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! CGELQ computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
               lminws = .true.
               mb = 1_${ik}$
               nb = n
             end if
             if( lwork<lwopt ) then
               lminws = .true.
               mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'CGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_cgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_claswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_cgelq

     pure module subroutine stdlib${ii}$_zgelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! ZGELQ computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if ( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
                 lminws = .true.
                 mb = 1_${ik}$
                 nb = n
             end if
             if( lwork<lwopt ) then
                 lminws = .true.
                 mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'ZGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_zgelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_zlaswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_zgelq

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gelq( m, n, a, lda, t, tsize, work, lwork,info )
     !! ZGELQ: computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, tsize, lwork
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: t(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery, lminws, mint, minw
           integer(${ik}$) :: mb, nb, mintsz, nblcks, lwmin, lwopt, lwreq
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           lquery = ( tsize==-1_${ik}$ .or. tsize==-2_${ik}$ .or.lwork==-1_${ik}$ .or. lwork==-2_${ik}$ )
           mint = .false.
           minw = .false.
           if( tsize==-2_${ik}$ .or. lwork==-2_${ik}$ ) then
             if( tsize/=-1_${ik}$ ) mint = .true.
             if( lwork/=-1_${ik}$ ) minw = .true.
           end if
           ! determine the block size
           if( min( m, n )>0_${ik}$ ) then
             mb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 1_${ik}$, -1_${ik}$ )
             nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQ ', ' ', m, n, 2_${ik}$, -1_${ik}$ )
           else
             mb = 1_${ik}$
             nb = n
           end if
           if( mb>min( m, n ) .or. mb<1_${ik}$ ) mb = 1_${ik}$
           if( nb>n .or. nb<=m ) nb = n
           mintsz = m + 5_${ik}$
           if ( nb>m .and. n>m ) then
             if( mod( n - m, nb - m )==0_${ik}$ ) then
               nblcks = ( n - m ) / ( nb - m )
             else
               nblcks = ( n - m ) / ( nb - m ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           ! determine if the workspace size satisfies minimal size
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwmin = max( 1_${ik}$, n )
              lwopt = max( 1_${ik}$, mb*n )
           else
              lwmin = max( 1_${ik}$, m )
              lwopt = max( 1_${ik}$, mb*m )
           end if
           lminws = .false.
           if( ( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) .or. lwork<lwopt ).and. ( lwork>=lwmin ) .and. ( &
                     tsize>=mintsz ).and. ( .not.lquery ) ) then
             if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ) ) then
                 lminws = .true.
                 mb = 1_${ik}$
                 nb = n
             end if
             if( lwork<lwopt ) then
                 lminws = .true.
                 mb = 1_${ik}$
             end if
           end if
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
              lwreq = max( 1_${ik}$, mb*n )
           else
              lwreq = max( 1_${ik}$, mb*m )
           end if
           if( m<0_${ik}$ ) then
             info = -1_${ik}$
           else if( n<0_${ik}$ ) then
             info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
             info = -4_${ik}$
           else if( tsize<max( 1_${ik}$, mb*m*nblcks + 5_${ik}$ ).and. ( .not.lquery ) .and. ( .not.lminws ) ) &
                     then
             info = -6_${ik}$
           else if( ( lwork<lwreq ) .and.( .not.lquery ).and. ( .not.lminws ) ) then
             info = -8_${ik}$
           end if
           if( info==0_${ik}$ ) then
             if( mint ) then
               t( 1_${ik}$ ) = mintsz
             else
               t( 1_${ik}$ ) = mb*m*nblcks + 5_${ik}$
             end if
             t( 2_${ik}$ ) = mb
             t( 3_${ik}$ ) = nb
             if( minw ) then
               work( 1_${ik}$ ) = lwmin
             else
               work( 1_${ik}$ ) = lwreq
             end if
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'ZGELQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n )==0_${ik}$ ) then
             return
           end if
           ! the lq decomposition
           if( ( n<=m ) .or. ( nb<=m ) .or. ( nb>=n ) ) then
             call stdlib${ii}$_${ci}$gelqt( m, n, mb, a, lda, t( 6_${ik}$ ), mb, work, info )
           else
             call stdlib${ii}$_${ci}$laswlq( m, n, mb, nb, a, lda, t( 6_${ik}$ ), mb, work,lwork, info )
           end if
           work( 1_${ik}$ ) = lwreq
           return
     end subroutine stdlib${ii}$_${ci}$gelq

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! SGEMLQ 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 defined as the product
     !! of blocked elementary reflectors computed by short wide LQ
     !! factorization (SGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           real(sp), intent(in) :: a(lda,*), t(*)
           real(sp), intent(inout) :: c(ldc,*)
           real(sp), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'T' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = real( lw,KIND=sp)
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'SGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_sgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_slamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = real( lw,KIND=sp)
           return
     end subroutine stdlib${ii}$_sgemlq

     pure module subroutine stdlib${ii}$_dgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! DGEMLQ 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 defined as the product
     !! of blocked elementary reflectors computed by short wide LQ
     !! factorization (DGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           real(dp), intent(in) :: a(lda,*), t(*)
           real(dp), intent(inout) :: c(ldc,*)
           real(dp), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'T' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = lw
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'DGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_dgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_dlamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = lw
           return
     end subroutine stdlib${ii}$_dgemlq

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! DGEMLQ: 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 defined as the product
     !! of blocked elementary reflectors computed by short wide LQ
     !! factorization (DGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           real(${rk}$), intent(in) :: a(lda,*), t(*)
           real(${rk}$), intent(inout) :: c(ldc,*)
           real(${rk}$), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'T' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = lw
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'DGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_${ri}$gemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_${ri}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = lw
           return
     end subroutine stdlib${ii}$_${ri}$gemlq

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! CGEMLQ overwrites the general real 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 defined as the product
     !! of blocked elementary reflectors computed by short wide
     !! LQ factorization (CGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           complex(sp), intent(in) :: a(lda,*), t(*)
           complex(sp), intent(inout) :: c(ldc,*)
           complex(sp), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'C' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = real( lw,KIND=sp)
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'CGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_cgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_clamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = real( lw,KIND=sp)
           return
     end subroutine stdlib${ii}$_cgemlq

     pure module subroutine stdlib${ii}$_zgemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! ZGEMLQ overwrites the general real 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 defined as the product
     !! of blocked elementary reflectors computed by short wide
     !! LQ factorization (ZGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           complex(dp), intent(in) :: a(lda,*), t(*)
           complex(dp), intent(inout) :: c(ldc,*)
           complex(dp), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'C' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = lw
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'ZGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_zgemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_zlamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = lw
           return
     end subroutine stdlib${ii}$_zgemlq

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gemlq( side, trans, m, n, k, a, lda, t, tsize,c, ldc, work, lwork, &
     !! ZGEMLQ: overwrites the general real 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 defined as the product
     !! of blocked elementary reflectors computed by short wide
     !! LQ factorization (ZGELQ)
               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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n, k, tsize, lwork, ldc
           ! Array Arguments 
           complex(${ck}$), intent(in) :: a(lda,*), t(*)
           complex(${ck}$), intent(inout) :: c(ldc,*)
           complex(${ck}$), intent(out) :: work(*)
       ! =====================================================================
           ! Local Scalars 
           logical(lk) :: left, right, tran, notran, lquery
           integer(${ik}$) :: mb, nb, lw, nblcks, mn
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           lquery  = lwork==-1_${ik}$
           notran  = stdlib_lsame( trans, 'N' )
           tran    = stdlib_lsame( trans, 'C' )
           left    = stdlib_lsame( side, 'L' )
           right   = stdlib_lsame( side, 'R' )
           mb = int( t( 2_${ik}$ ),KIND=${ik}$)
           nb = int( t( 3_${ik}$ ),KIND=${ik}$)
           if( left ) then
             lw = n * mb
             mn = m
           else
             lw = m * mb
             mn = n
           end if
           if( ( nb>k ) .and. ( mn>k ) ) then
             if( mod( mn - k, nb - k ) == 0_${ik}$ ) then
               nblcks = ( mn - k ) / ( nb - k )
             else
               nblcks = ( mn - k ) / ( nb - k ) + 1_${ik}$
             end if
           else
             nblcks = 1_${ik}$
           end if
           info = 0_${ik}$
           if( .not.left .and. .not.right ) then
             info = -1_${ik}$
           else if( .not.tran .and. .not.notran ) then
             info = -2_${ik}$
           else if( m<0_${ik}$ ) then
             info = -3_${ik}$
           else if( n<0_${ik}$ ) then
             info = -4_${ik}$
           else if( k<0_${ik}$ .or. k>mn ) then
             info = -5_${ik}$
           else if( lda<max( 1_${ik}$, k ) ) then
             info = -7_${ik}$
           else if( tsize<5_${ik}$ ) then
             info = -9_${ik}$
           else if( ldc<max( 1_${ik}$, m ) ) then
             info = -11_${ik}$
           else if( ( lwork<max( 1_${ik}$, lw ) ) .and. ( .not.lquery ) ) then
             info = -13_${ik}$
           end if
           if( info==0_${ik}$ ) then
             work( 1_${ik}$ ) = lw
           end if
           if( info/=0_${ik}$ ) then
             call stdlib${ii}$_xerbla( 'ZGEMLQ', -info )
             return
           else if( lquery ) then
             return
           end if
           ! quick return if possible
           if( min( m, n, k )==0_${ik}$ ) then
             return
           end if
           if( ( left .and. m<=k ) .or. ( right .and. n<=k ).or. ( nb<=k ) .or. ( nb>=max( m, n, &
                     k ) ) ) then
             call stdlib${ii}$_${ci}$gemlqt( side, trans, m, n, k, mb, a, lda,t( 6_${ik}$ ), mb, c, ldc, work, info &
                       )
           else
             call stdlib${ii}$_${ci}$lamswlq( side, trans, m, n, k, mb, nb, a, lda, t( 6_${ik}$ ),mb, c, ldc, work, &
                       lwork, info )
           end if
           work( 1_${ik}$ ) = lw
           return
     end subroutine stdlib${ii}$_${ci}$gemlq

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgelqf( m, n, a, lda, tau, work, lwork, info )
     !! SGELQF computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'SGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_sgelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_slarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_slarfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_sgelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_sgelqf

     pure module subroutine stdlib${ii}$_dgelqf( m, n, a, lda, tau, work, lwork, info )
     !! DGELQF computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_dgelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_dlarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_dlarfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_dgelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_dgelqf

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gelqf( m, n, a, lda, tau, work, lwork, info )
     !! DGELQF: computes an LQ factorization of a real M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'DGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_${ri}$gelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_${ri}$larft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_${ri}$larfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_${ri}$gelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_${ri}$gelqf

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgelqf( m, n, a, lda, tau, work, lwork, info )
     !! CGELQF computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'CGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'CGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_cgelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_clarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_clarfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_cgelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_cgelqf

     pure module subroutine stdlib${ii}$_zgelqf( m, n, a, lda, tau, work, lwork, info )
     !! ZGELQF computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_zgelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_zlarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_zlarfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_zgelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_zgelqf

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gelqf( m, n, a, lda, tau, work, lwork, info )
     !! ZGELQF: computes an LQ factorization of a complex M-by-N matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a N-by-N orthogonal matrix;
     !! L is a lower-triangular M-by-M matrix;
     !! 0 is a M-by-(N-M) zero matrix, if M < N.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, lwork, m, n
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, ib, iinfo, iws, k, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
           lwkopt = m*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -7_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGELQF', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           k = min( m, n )
           if( k==0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZGELQF', ' ', m, n, -1_${ik}$,-1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code initially
              do i = 1, k - nx, nb
                 ib = min( k-i+1, nb )
                 ! compute the lq factorization of the current block
                 ! a(i:i+ib-1,i:n)
                 call stdlib${ii}$_${ci}$gelq2( ib, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_${ci}$larft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_${ci}$larfb( 'RIGHT', 'NO TRANSPOSE', 'FORWARD','ROWWISE', m-i-ib+1, n-&
                    i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), ldwork )
                              
                 end if
              end do
           else
              i = 1_${ik}$
           end if
           ! use unblocked code to factor the last or only block.
           if( i<=k )call stdlib${ii}$_${ci}$gelq2( m-i+1, n-i+1, a( i, i ), lda, tau( i ), work,iinfo )
                     
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_${ci}$gelqf

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sgelq2( m, n, a, lda, tau, work, info )
     !! SGELQ2 computes an LQ factorization of a real m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*)
           real(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           real(sp) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_slarfg( n-i+1, a( i, i ), a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 aii = a( i, i )
                 a( i, i ) = one
                 call stdlib${ii}$_slarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
                 a( i, i ) = aii
              end if
           end do
           return
     end subroutine stdlib${ii}$_sgelq2

     pure module subroutine stdlib${ii}$_dgelq2( m, n, a, lda, tau, work, info )
     !! DGELQ2 computes an LQ factorization of a real m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*)
           real(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           real(dp) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_dlarfg( n-i+1, a( i, i ), a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 aii = a( i, i )
                 a( i, i ) = one
                 call stdlib${ii}$_dlarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
                 a( i, i ) = aii
              end if
           end do
           return
     end subroutine stdlib${ii}$_dgelq2

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gelq2( m, n, a, lda, tau, work, info )
     !! DGELQ2: computes an LQ factorization of a real m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*)
           real(${rk}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           real(${rk}$) :: aii
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_${ri}$larfg( n-i+1, a( i, i ), a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 aii = a( i, i )
                 a( i, i ) = one
                 call stdlib${ii}$_${ri}$larf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
                 a( i, i ) = aii
              end if
           end do
           return
     end subroutine stdlib${ii}$_${ri}$gelq2

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgelq2( m, n, a, lda, tau, work, info )
     !! CGELQ2 computes an LQ factorization of a complex m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           complex(sp) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_clacgv( n-i+1, a( i, i ), lda )
              alpha = a( i, i )
              call stdlib${ii}$_clarfg( n-i+1, alpha, a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 a( i, i ) = cone
                 call stdlib${ii}$_clarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
              end if
              a( i, i ) = alpha
              call stdlib${ii}$_clacgv( n-i+1, a( i, i ), lda )
           end do
           return
     end subroutine stdlib${ii}$_cgelq2

     pure module subroutine stdlib${ii}$_zgelq2( m, n, a, lda, tau, work, info )
     !! ZGELQ2 computes an LQ factorization of a complex m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           complex(dp) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_zlacgv( n-i+1, a( i, i ), lda )
              alpha = a( i, i )
              call stdlib${ii}$_zlarfg( n-i+1, alpha, a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 a( i, i ) = cone
                 call stdlib${ii}$_zlarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
              end if
              a( i, i ) = alpha
              call stdlib${ii}$_zlacgv( n-i+1, a( i, i ), lda )
           end do
           return
     end subroutine stdlib${ii}$_zgelq2

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gelq2( m, n, a, lda, tau, work, info )
     !! ZGELQ2: computes an LQ factorization of a complex m-by-n matrix A:
     !! A = ( L 0 ) *  Q
     !! where:
     !! Q is a n-by-n orthogonal matrix;
     !! L is a lower-triangular m-by-m matrix;
     !! 0 is a m-by-(n-m) zero matrix, if m < n.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: lda, m, n
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(out) :: tau(*), work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, k
           complex(${ck}$) :: alpha
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -4_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGELQ2', -info )
              return
           end if
           k = min( m, n )
           do i = 1, k
              ! generate elementary reflector h(i) to annihilate a(i,i+1:n)
              call stdlib${ii}$_${ci}$lacgv( n-i+1, a( i, i ), lda )
              alpha = a( i, i )
              call stdlib${ii}$_${ci}$larfg( n-i+1, alpha, a( i, min( i+1, n ) ), lda,tau( i ) )
              if( i<m ) then
                 ! apply h(i) to a(i+1:m,i:n) from the right
                 a( i, i ) = cone
                 call stdlib${ii}$_${ci}$larf( 'RIGHT', m-i, n-i+1, a( i, i ), lda, tau( i ),a( i+1, i ), &
                           lda, work )
              end if
              a( i, i ) = alpha
              call stdlib${ii}$_${ci}$lacgv( n-i+1, a( i, i ), lda )
           end do
           return
     end subroutine stdlib${ii}$_${ci}$gelq2

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_cunglq( m, n, k, a, lda, tau, work, lwork, info )
     !! CUNGLQ generates an M-by-N complex matrix Q with orthonormal rows,
     !! which is defined as the first M rows of a product of K elementary
     !! reflectors of order N
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by CGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, lwork, m, n
           ! 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, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNGLQ', ' ', m, n, k, -1_${ik}$ )
           lwkopt = max( 1_${ik}$, m )*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CUNGLQ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m<=0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'CUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'CUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code after the last block.
              ! the first kk rows are handled by the block method.
              ki = ( ( k-nx-1 ) / nb )*nb
              kk = min( k, ki+nb )
              ! set a(kk+1:m,1:kk) to czero.
              do j = 1, kk
                 do i = kk + 1, m
                    a( i, j ) = czero
                 end do
              end do
           else
              kk = 0_${ik}$
           end if
           ! use unblocked code for the last or only block.
           if( kk<m )call stdlib${ii}$_cungl2( m-kk, n-kk, k-kk, a( kk+1, kk+1 ), lda,tau( kk+1 ), work,&
                      iinfo )
           if( kk>0_${ik}$ ) then
              ! use blocked code
              do i = ki + 1, 1, -nb
                 ib = min( nb, k-i+1 )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_clarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h**h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_clarfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-&
                    ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), &
                              ldwork )
                 end if
                 ! apply h**h to columns i:n of current block
                 call stdlib${ii}$_cungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo )
                 ! set columns 1:i-1 of current block to czero
                 do j = 1, i - 1
                    do l = i, i + ib - 1
                       a( l, j ) = czero
                    end do
                 end do
              end do
           end if
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_cunglq

     pure module subroutine stdlib${ii}$_zunglq( m, n, k, a, lda, tau, work, lwork, info )
     !! ZUNGLQ generates an M-by-N complex matrix Q with orthonormal rows,
     !! which is defined as the first M rows of a product of K elementary
     !! reflectors of order N
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by ZGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, lwork, m, n
           ! 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, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ )
           lwkopt = max( 1_${ik}$, m )*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGLQ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m<=0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code after the last block.
              ! the first kk rows are handled by the block method.
              ki = ( ( k-nx-1 ) / nb )*nb
              kk = min( k, ki+nb )
              ! set a(kk+1:m,1:kk) to czero.
              do j = 1, kk
                 do i = kk + 1, m
                    a( i, j ) = czero
                 end do
              end do
           else
              kk = 0_${ik}$
           end if
           ! use unblocked code for the last or only block.
           if( kk<m )call stdlib${ii}$_zungl2( m-kk, n-kk, k-kk, a( kk+1, kk+1 ), lda,tau( kk+1 ), work,&
                      iinfo )
           if( kk>0_${ik}$ ) then
              ! use blocked code
              do i = ki + 1, 1, -nb
                 ib = min( nb, k-i+1 )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_zlarft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h**h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_zlarfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-&
                    ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), &
                              ldwork )
                 end if
                 ! apply h**h to columns i:n of current block
                 call stdlib${ii}$_zungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo )
                 ! set columns 1:i-1 of current block to czero
                 do j = 1, i - 1
                    do l = i, i + ib - 1
                       a( l, j ) = czero
                    end do
                 end do
              end do
           end if
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_zunglq

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$unglq( m, n, k, a, lda, tau, work, lwork, info )
     !! ZUNGLQ: generates an M-by-N complex matrix Q with orthonormal rows,
     !! which is defined as the first M rows of a product of K elementary
     !! reflectors of order N
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by ZGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, lwork, m, n
           ! 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, ib, iinfo, iws, j, ki, kk, l, ldwork, lwkopt, nb, nbmin, nx
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           nb = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ )
           lwkopt = max( 1_${ik}$, m )*nb
           work( 1_${ik}$ ) = lwkopt
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( lwork<max( 1_${ik}$, m ) .and. .not.lquery ) then
              info = -8_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGLQ', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( m<=0_${ik}$ ) then
              work( 1_${ik}$ ) = 1_${ik}$
              return
           end if
           nbmin = 2_${ik}$
           nx = 0_${ik}$
           iws = m
           if( nb>1_${ik}$ .and. nb<k ) then
              ! determine when to cross over from blocked to unblocked code.
              nx = max( 0_${ik}$, stdlib${ii}$_ilaenv( 3_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
              if( nx<k ) then
                 ! determine if workspace is large enough for blocked code.
                 ldwork = m
                 iws = ldwork*nb
                 if( lwork<iws ) then
                    ! not enough workspace to use optimal nb:  reduce nb and
                    ! determine the minimum value of nb.
                    nb = lwork / ldwork
                    nbmin = max( 2_${ik}$, stdlib${ii}$_ilaenv( 2_${ik}$, 'ZUNGLQ', ' ', m, n, k, -1_${ik}$ ) )
                 end if
              end if
           end if
           if( nb>=nbmin .and. nb<k .and. nx<k ) then
              ! use blocked code after the last block.
              ! the first kk rows are handled by the block method.
              ki = ( ( k-nx-1 ) / nb )*nb
              kk = min( k, ki+nb )
              ! set a(kk+1:m,1:kk) to czero.
              do j = 1, kk
                 do i = kk + 1, m
                    a( i, j ) = czero
                 end do
              end do
           else
              kk = 0_${ik}$
           end if
           ! use unblocked code for the last or only block.
           if( kk<m )call stdlib${ii}$_${ci}$ungl2( m-kk, n-kk, k-kk, a( kk+1, kk+1 ), lda,tau( kk+1 ), work,&
                      iinfo )
           if( kk>0_${ik}$ ) then
              ! use blocked code
              do i = ki + 1, 1, -nb
                 ib = min( nb, k-i+1 )
                 if( i+ib<=m ) then
                    ! form the triangular factor of the block reflector
                    ! h = h(i) h(i+1) . . . h(i+ib-1)
                    call stdlib${ii}$_${ci}$larft( 'FORWARD', 'ROWWISE', n-i+1, ib, a( i, i ),lda, tau( i ), &
                              work, ldwork )
                    ! apply h**h to a(i+ib:m,i:n) from the right
                    call stdlib${ii}$_${ci}$larfb( 'RIGHT', 'CONJUGATE TRANSPOSE', 'FORWARD','ROWWISE', m-i-&
                    ib+1, n-i+1, ib, a( i, i ),lda, work, ldwork, a( i+ib, i ), lda,work( ib+1 ), &
                              ldwork )
                 end if
                 ! apply h**h to columns i:n of current block
                 call stdlib${ii}$_${ci}$ungl2( ib, n-i+1, ib, a( i, i ), lda, tau( i ), work,iinfo )
                 ! set columns 1:i-1 of current block to czero
                 do j = 1, i - 1
                    do l = i, i + ib - 1
                       a( l, j ) = czero
                    end do
                 end do
              end do
           end if
           work( 1_${ik}$ ) = iws
           return
     end subroutine stdlib${ii}$_${ci}$unglq

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_cungl2( m, n, k, a, lda, tau, work, info )
     !! CUNGL2 generates an m-by-n complex matrix Q with orthonormal rows,
     !! which is defined as the first m rows of a product of k elementary
     !! reflectors of order n
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by CGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, m, n
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*)
           complex(sp), intent(in) :: tau(*)
           complex(sp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, j, l
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CUNGL2', -info )
              return
           end if
           ! quick return if possible
           if( m<=0 )return
           if( k<m ) then
              ! initialise rows k+1:m to rows of the unit matrix
              do j = 1, n
                 do l = k + 1, m
                    a( l, j ) = czero
                 end do
                 if( j>k .and. j<=m )a( j, j ) = cone
              end do
           end if
           do i = k, 1, -1
              ! apply h(i)**h to a(i:m,i:n) from the right
              if( i<n ) then
                 call stdlib${ii}$_clacgv( n-i, a( i, i+1 ), lda )
                 if( i<m ) then
                    a( i, i ) = cone
                    call stdlib${ii}$_clarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda,conjg( tau( i ) ), a( &
                              i+1, i ), lda, work )
                 end if
                 call stdlib${ii}$_cscal( n-i, -tau( i ), a( i, i+1 ), lda )
                 call stdlib${ii}$_clacgv( n-i, a( i, i+1 ), lda )
              end if
              a( i, i ) = cone - conjg( tau( i ) )
              ! set a(i,1:i-1,i) to czero
              do l = 1, i - 1
                 a( i, l ) = czero
              end do
           end do
           return
     end subroutine stdlib${ii}$_cungl2

     pure module subroutine stdlib${ii}$_zungl2( m, n, k, a, lda, tau, work, info )
     !! ZUNGL2 generates an m-by-n complex matrix Q with orthonormal rows,
     !! which is defined as the first m rows of a product of k elementary
     !! reflectors of order n
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by ZGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, m, n
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*)
           complex(dp), intent(in) :: tau(*)
           complex(dp), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, j, l
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGL2', -info )
              return
           end if
           ! quick return if possible
           if( m<=0 )return
           if( k<m ) then
              ! initialise rows k+1:m to rows of the unit matrix
              do j = 1, n
                 do l = k + 1, m
                    a( l, j ) = czero
                 end do
                 if( j>k .and. j<=m )a( j, j ) = cone
              end do
           end if
           do i = k, 1, -1
              ! apply h(i)**h to a(i:m,i:n) from the right
              if( i<n ) then
                 call stdlib${ii}$_zlacgv( n-i, a( i, i+1 ), lda )
                 if( i<m ) then
                    a( i, i ) = cone
                    call stdlib${ii}$_zlarf( 'RIGHT', m-i, n-i+1, a( i, i ), lda,conjg( tau( i ) ), a( &
                              i+1, i ), lda, work )
                 end if
                 call stdlib${ii}$_zscal( n-i, -tau( i ), a( i, i+1 ), lda )
                 call stdlib${ii}$_zlacgv( n-i, a( i, i+1 ), lda )
              end if
              a( i, i ) = cone - conjg( tau( i ) )
              ! set a(i,1:i-1) to czero
              do l = 1, i - 1
                 a( i, l ) = czero
              end do
           end do
           return
     end subroutine stdlib${ii}$_zungl2

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$ungl2( m, n, k, a, lda, tau, work, info )
     !! ZUNGL2: generates an m-by-n complex matrix Q with orthonormal rows,
     !! which is defined as the first m rows of a product of k elementary
     !! reflectors of order n
     !! Q  =  H(k)**H . . . H(2)**H H(1)**H
     !! as returned by ZGELQF.
        ! -- 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(out) :: info
           integer(${ik}$), intent(in) :: k, lda, m, n
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*)
           complex(${ck}$), intent(in) :: tau(*)
           complex(${ck}$), intent(out) :: work(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: i, j, l
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input arguments
           info = 0_${ik}$
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<m ) then
              info = -2_${ik}$
           else if( k<0_${ik}$ .or. k>m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZUNGL2', -info )
              return
           end if
           ! quick return if possible
           if( m<=0 )return
           if( k<m ) then
              ! initialise rows k+1:m to rows of the unit matrix
              do j = 1, n
                 do l = k + 1, m
                    a( l, j ) = czero
                 end do
                 if( j>k .and. j<=m )a( j, j ) = cone
              end do
           end if
           do i = k, 1, -1
              ! apply h(i)**h to a(i:m,i:n) from the right
              if( i<n ) then
                 call stdlib${ii}$_${ci}$lacgv( n-i, a( i, i+1 ), lda )
                 if( i<m ) then
                    a( i, i ) = cone
                    call stdlib${ii}$_${ci}$larf( 'RIGHT', m-i, n-i+1, a( i, i ), lda,conjg( tau( i ) ), a( &
                              i+1, i ), lda, work )
                 end if
                 call stdlib${ii}$_${ci}$scal( n-i, -tau(