stdlib_lapack_lsq_constrained.fypp Source File


Source Code

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


  contains
#:for ik,it,ii in LINALG_INT_KINDS_TYPES

     pure module subroutine stdlib${ii}$_sgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! SGGLSE solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           real(sp), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**t = (  0  t12 ) p   z**t*a*q**t = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_sggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = work( p+mn+1 )
           ! update c = z**t *c = ( c1 ) n-p
                                ! ( c2 ) m+p-n
           call stdlib${ii}$_sormqr( 'LEFT', 'TRANSPOSE', m, 1_${ik}$, mn, a, lda, work( p+1 ),c, max( 1_${ik}$, m ), &
                     work( p+mn+1 ), lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
              call stdlib${ii}$_scopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_sgemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ &
                        )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_scopy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_sgemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( &
                        nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_strmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_saxpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**t*x
           call stdlib${ii}$_sormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 &
                     ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_sgglse

     pure module subroutine stdlib${ii}$_dgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! DGGLSE solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           real(dp), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**t = (  0  t12 ) p   z**t*a*q**t = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_dggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = work( p+mn+1 )
           ! update c = z**t *c = ( c1 ) n-p
                                ! ( c2 ) m+p-n
           call stdlib${ii}$_dormqr( 'LEFT', 'TRANSPOSE', m, 1_${ik}$, mn, a, lda, work( p+1 ),c, max( 1_${ik}$, m ), &
                     work( p+mn+1 ), lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
              call stdlib${ii}$_dcopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_dgemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ &
                        )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_dcopy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_dgemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( &
                        nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_dtrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_daxpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**t*x
           call stdlib${ii}$_dormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 &
                     ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_dgglse

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$gglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! DGGLSE: solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           real(${rk}$), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**t = (  0  t12 ) p   z**t*a*q**t = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_${ri}$ggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = work( p+mn+1 )
           ! update c = z**t *c = ( c1 ) n-p
                                ! ( c2 ) m+p-n
           call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'TRANSPOSE', m, 1_${ik}$, mn, a, lda, work( p+1 ),c, max( 1_${ik}$, m ), &
                     work( p+mn+1 ), lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
              call stdlib${ii}$_${ri}$copy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', n-p, p, -one, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, one, c, 1_${ik}$ &
                        )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_${ri}$copy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', nr, n-m, -one, a( n-p+1, m+1 ),lda, d( &
                        nr+1 ), 1_${ik}$, one, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_${ri}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_${ri}$axpy( nr, -one, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**t*x
           call stdlib${ii}$_${ri}$ormrq( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, p, b, ldb, work( 1_${ik}$ ), x,n, work( p+mn+1 &
                     ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_${ri}$gglse

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! CGGLSE solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           complex(sp), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**h = (  0  t12 ) p   z**h*a*q**h = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_cggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = real( work( p+mn+1 ),KIND=sp)
           ! update c = z**h *c = ( c1 ) n-p
                             ! ( c2 ) m+p-n
           call stdlib${ii}$_cunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, 1_${ik}$, mn, a, lda,work( p+1 ), c, &
                     max( 1_${ik}$, m ), work( p+mn+1 ),lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
           call stdlib${ii}$_ccopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_cgemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, &
                        1_${ik}$ )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_ccopy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_cgemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(&
                         nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_ctrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_caxpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**h*x
           call stdlib${ii}$_cunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, &
                     work( p+mn+1 ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_cgglse

     pure module subroutine stdlib${ii}$_zgglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! ZGGLSE solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           complex(dp), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**h = (  0  t12 ) p   z**h*a*q**h = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_zggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = real( work( p+mn+1 ),KIND=dp)
           ! update c = z**h *c = ( c1 ) n-p
                             ! ( c2 ) m+p-n
           call stdlib${ii}$_zunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, 1_${ik}$, mn, a, lda,work( p+1 ), c, &
                     max( 1_${ik}$, m ), work( p+mn+1 ),lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
              call stdlib${ii}$_zcopy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_zgemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, &
                        1_${ik}$ )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_zcopy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_zgemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(&
                         nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_ztrmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_zaxpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**h*x
           call stdlib${ii}$_zunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, &
                     work( p+mn+1 ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_zgglse

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$gglse( m, n, p, a, lda, b, ldb, c, d, x, work, lwork,info )
     !! ZGGLSE: solves the linear equality-constrained least squares (LSE)
     !! problem:
     !! minimize || c - A*x ||_2   subject to   B*x = d
     !! where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
     !! M-vector, and d is a given P-vector. It is assumed that
     !! P <= N <= M+P, and
     !! rank(B) = P and  rank( (A) ) = N.
     !! ( (B) )
     !! These conditions ensure that the LSE problem has a unique solution,
     !! which is obtained using a generalized RQ factorization of the
     !! matrices (B, A) given by
     !! B = (0 R)*Q,   A = Z*T*Q.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), c(*), d(*)
           complex(${ck}$), intent(out) :: work(*), x(*)
        ! =====================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: lopt, lwkmin, lwkopt, mn, nb, nb1, nb2, nb3, nb4, nr
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           mn = min( m, n )
           lquery = ( lwork==-1_${ik}$ )
           if( m<0_${ik}$ ) then
              info = -1_${ik}$
           else if( n<0_${ik}$ ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p>n .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, m ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGERQF', ' ', m, n, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', m, n, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMRQ', ' ', m, n, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = p + mn + max( m, n )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGLSE', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0 )return
           ! compute the grq factorization of matrices b and a:
                  ! b*q**h = (  0  t12 ) p   z**h*a*q**h = ( r11 r12 ) n-p
                              ! n-p  p                     (  0  r22 ) m+p-n
                                                            ! n-p  p
           ! where t12 and r11 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_${ci}$ggrqf( p, m, n, b, ldb, work, a, lda, work( p+1 ),work( p+mn+1 ), lwork-p-&
                     mn, info )
           lopt = real( work( p+mn+1 ),KIND=${ck}$)
           ! update c = z**h *c = ( c1 ) n-p
                             ! ( c2 ) m+p-n
           call stdlib${ii}$_${ci}$unmqr( 'LEFT', 'CONJUGATE TRANSPOSE', m, 1_${ik}$, mn, a, lda,work( p+1 ), c, &
                     max( 1_${ik}$, m ), work( p+mn+1 ),lwork-p-mn, info )
           lopt = max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           ! solve t12*x2 = d for x2
           if( p>0_${ik}$ ) then
              call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', p, 1_${ik}$,b( 1_${ik}$, n-p+1 ), ldb, d,&
                         p, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              ! put the solution in x
              call stdlib${ii}$_${ci}$copy( p, d, 1_${ik}$, x( n-p+1 ), 1_${ik}$ )
              ! update c1
              call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', n-p, p, -cone, a( 1_${ik}$, n-p+1 ), lda,d, 1_${ik}$, cone, c, &
                        1_${ik}$ )
           end if
           ! solve r11*x1 = c1 for x1
           if( n>p ) then
              call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON-UNIT', n-p, 1_${ik}$,a, lda, c, n-p, &
                        info )
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! put the solutions in x
              call stdlib${ii}$_${ci}$copy( n-p, c, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! compute the residual vector:
           if( m<n ) then
              nr = m + p - n
              if( nr>0_${ik}$ )call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', nr, n-m, -cone, a( n-p+1, m+1 ),lda, d(&
                         nr+1 ), 1_${ik}$, cone, c( n-p+1 ), 1_${ik}$ )
           else
              nr = p
           end if
           if( nr>0_${ik}$ ) then
              call stdlib${ii}$_${ci}$trmv( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', nr,a( n-p+1, n-p+1 ), lda, &
                        d, 1_${ik}$ )
              call stdlib${ii}$_${ci}$axpy( nr, -cone, d, 1_${ik}$, c( n-p+1 ), 1_${ik}$ )
           end if
           ! backward transformation x = q**h*x
           call stdlib${ii}$_${ci}$unmrq( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, p, b, ldb,work( 1_${ik}$ ), x, n, &
                     work( p+mn+1 ), lwork-p-mn, info )
           work( 1_${ik}$ ) = p + mn + max( lopt, int( work( p+mn+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_${ci}$gglse

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! SGGGLM solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(sp), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           real(sp), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'SORMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = zero
              end do
              do i = 1, p
                 y(i) = zero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**t*a = ( r11 ) m,    q**t*b*z**t = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_sggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = work( m+np+1 )
           ! update left-hand-side vector d = q**t*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_sormqr( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, m, a, lda, work, d,max( 1_${ik}$, n ), work( m+&
                     np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_scopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = zero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_sgemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, &
                     one, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_strtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_scopy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**t *y
           call stdlib${ii}$_sormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( &
                     m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_sggglm

     pure module subroutine stdlib${ii}$_dggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! DGGGLM solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(dp), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           real(dp), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = zero
              end do
              do i = 1, p
                 y(i) = zero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**t*a = ( r11 ) m,    q**t*b*z**t = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_dggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = work( m+np+1 )
           ! update left-hand-side vector d = q**t*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_dormqr( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, m, a, lda, work, d,max( 1_${ik}$, n ), work( m+&
                     np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_dcopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = zero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_dgemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, &
                     one, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_dtrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_dcopy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**t *y
           call stdlib${ii}$_dormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( &
                     m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_dggglm

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$ggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! DGGGLM: solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           real(${rk}$), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           real(${rk}$), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'DORMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = zero
              end do
              do i = 1, p
                 y(i) = zero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**t*a = ( r11 ) m,    q**t*b*z**t = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! orthogonal.
           call stdlib${ii}$_${ri}$ggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = work( m+np+1 )
           ! update left-hand-side vector d = q**t*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_${ri}$ormqr( 'LEFT', 'TRANSPOSE', n, 1_${ik}$, m, a, lda, work, d,max( 1_${ik}$, n ), work( m+&
                     np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_${ri}$copy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = zero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_${ri}$gemv( 'NO TRANSPOSE', m, n-m, -one, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$, &
                     one, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_${ri}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_${ri}$copy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**t *y
           call stdlib${ii}$_${ri}$ormrq( 'LEFT', 'TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), ldb, work( &
                     m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_${ri}$ggglm

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_cggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! CGGGLM solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(sp), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           complex(sp), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'CUNMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'CGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = czero
              end do
              do i = 1, p
                 y(i) = czero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**h*a = ( r11 ) m,    q**h*b*z**h = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_cggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = real( work( m+np+1 ),KIND=sp)
           ! update left-hand-side vector d = q**h*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_cunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, m, a, lda, work,d, max( 1_${ik}$, n )&
                     , work( m+np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_ccopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = czero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_cgemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,&
                      cone, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_ctrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_ccopy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**h *y
           call stdlib${ii}$_cunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), &
                     ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_cggglm

     pure module subroutine stdlib${ii}$_zggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! ZGGGLM solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(dp), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           complex(dp), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = czero
              end do
              do i = 1, p
                 y(i) = czero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**h*a = ( r11 ) m,    q**h*b*z**h = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_zggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = real( work( m+np+1 ),KIND=dp)
           ! update left-hand-side vector d = q**h*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_zunmqr( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, m, a, lda, work,d, max( 1_${ik}$, n )&
                     , work( m+np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_zcopy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = czero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_zgemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,&
                      cone, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_ztrtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_zcopy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**h *y
           call stdlib${ii}$_zunmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), &
                     ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_zggglm

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$ggglm( n, m, p, a, lda, b, ldb, d, x, y, work, lwork,info )
     !! ZGGGLM: solves a general Gauss-Markov linear model (GLM) problem:
     !! minimize || y ||_2   subject to   d = A*x + B*y
     !! x
     !! where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
     !! given N-vector. It is assumed that M <= N <= M+P, and
     !! rank(A) = M    and    rank( A B ) = N.
     !! Under these assumptions, the constrained equation is always
     !! consistent, and there is a unique solution x and a minimal 2-norm
     !! solution y, which is obtained using a generalized QR factorization
     !! of the matrices (A, B) given by
     !! A = Q*(R),   B = Q*T*Z.
     !! (0)
     !! In particular, if matrix B is square nonsingular, then the problem
     !! GLM is equivalent to the following weighted linear least squares
     !! problem
     !! minimize || inv(B)*(d-A*x) ||_2
     !! x
     !! where inv(B) denotes the inverse of B.
        ! -- lapack driver routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lda, ldb, lwork, m, n, p
           ! Array Arguments 
           complex(${ck}$), intent(inout) :: a(lda,*), b(ldb,*), d(*)
           complex(${ck}$), intent(out) :: work(*), x(*), y(*)
        ! ===================================================================
           
           ! Local Scalars 
           logical(lk) :: lquery
           integer(${ik}$) :: i, lopt, lwkmin, lwkopt, nb, nb1, nb2, nb3, nb4, np
           ! Intrinsic Functions 
           ! Executable Statements 
           ! test the input parameters
           info = 0_${ik}$
           np = min( n, p )
           lquery = ( lwork==-1_${ik}$ )
           if( n<0_${ik}$ ) then
              info = -1_${ik}$
           else if( m<0_${ik}$ .or. m>n ) then
              info = -2_${ik}$
           else if( p<0_${ik}$ .or. p<n-m ) then
              info = -3_${ik}$
           else if( lda<max( 1_${ik}$, n ) ) then
              info = -5_${ik}$
           else if( ldb<max( 1_${ik}$, n ) ) then
              info = -7_${ik}$
           end if
           ! calculate workspace
           if( info==0_${ik}$) then
              if( n==0_${ik}$ ) then
                 lwkmin = 1_${ik}$
                 lwkopt = 1_${ik}$
              else
                 nb1 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGEQRF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb2 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZGERQF', ' ', n, m, -1_${ik}$, -1_${ik}$ )
                 nb3 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMQR', ' ', n, m, p, -1_${ik}$ )
                 nb4 = stdlib${ii}$_ilaenv( 1_${ik}$, 'ZUNMRQ', ' ', n, m, p, -1_${ik}$ )
                 nb = max( nb1, nb2, nb3, nb4 )
                 lwkmin = m + n + p
                 lwkopt = m + np + max( n, p )*nb
              end if
              work( 1_${ik}$ ) = lwkopt
              if( lwork<lwkmin .and. .not.lquery ) then
                 info = -12_${ik}$
              end if
           end if
           if( info/=0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'ZGGGLM', -info )
              return
           else if( lquery ) then
              return
           end if
           ! quick return if possible
           if( n==0_${ik}$ ) then
              do i = 1, m
                 x(i) = czero
              end do
              do i = 1, p
                 y(i) = czero
              end do
              return
           end if
           ! compute the gqr factorization of matrices a and b:
                ! q**h*a = ( r11 ) m,    q**h*b*z**h = ( t11   t12 ) m
                         ! (  0  ) n-m                 (  0    t22 ) n-m
                            ! m                         m+p-n  n-m
           ! where r11 and t22 are upper triangular, and q and z are
           ! unitary.
           call stdlib${ii}$_${ci}$ggqrf( n, m, p, a, lda, work, b, ldb, work( m+1 ),work( m+np+1 ), lwork-m-&
                     np, info )
           lopt = real( work( m+np+1 ),KIND=${ck}$)
           ! update left-hand-side vector d = q**h*d = ( d1 ) m
                                                     ! ( d2 ) n-m
           call stdlib${ii}$_${ci}$unmqr( 'LEFT', 'CONJUGATE TRANSPOSE', n, 1_${ik}$, m, a, lda, work,d, max( 1_${ik}$, n )&
                     , work( m+np+1 ), lwork-m-np, info )
           lopt = max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           ! solve t22*y2 = d2 for y2
           if( n>m ) then
              call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', n-m, 1_${ik}$,b( m+1, m+p-n+1 ), &
                        ldb, d( m+1 ), n-m, info )
              if( info>0_${ik}$ ) then
                 info = 1_${ik}$
                 return
              end if
              call stdlib${ii}$_${ci}$copy( n-m, d( m+1 ), 1_${ik}$, y( m+p-n+1 ), 1_${ik}$ )
           end if
           ! set y1 = 0
           do i = 1, m + p - n
              y( i ) = czero
           end do
           ! update d1 = d1 - t12*y2
           call stdlib${ii}$_${ci}$gemv( 'NO TRANSPOSE', m, n-m, -cone, b( 1_${ik}$, m+p-n+1 ), ldb,y( m+p-n+1 ), 1_${ik}$,&
                      cone, d, 1_${ik}$ )
           ! solve triangular system: r11*x = d1
           if( m>0_${ik}$ ) then
              call stdlib${ii}$_${ci}$trtrs( 'UPPER', 'NO TRANSPOSE', 'NON UNIT', m, 1_${ik}$, a, lda,d, m, info )
                        
              if( info>0_${ik}$ ) then
                 info = 2_${ik}$
                 return
              end if
              ! copy d to x
              call stdlib${ii}$_${ci}$copy( m, d, 1_${ik}$, x, 1_${ik}$ )
           end if
           ! backward transformation y = z**h *y
           call stdlib${ii}$_${ci}$unmrq( 'LEFT', 'CONJUGATE TRANSPOSE', p, 1_${ik}$, np,b( max( 1_${ik}$, n-p+1 ), 1_${ik}$ ), &
                     ldb, work( m+1 ), y,max( 1_${ik}$, p ), work( m+np+1 ), lwork-m-np, info )
           work( 1_${ik}$ ) = m + np + max( lopt, int( work( m+np+1 ),KIND=${ik}$) )
           return
     end subroutine stdlib${ii}$_${ci}$ggglm

#:endif
#:endfor


#:endfor
end submodule stdlib_lapack_lsq_constrained