stdlib_lapack_cosine_sine2.fypp Source File


Source Code

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


  contains
#:for ik,it,ii in LINALG_INT_KINDS_TYPES

     recursive module subroutine stdlib${ii}$_sorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, &
     !! SORCSD computes the CS decomposition of an M-by-M partitioned
     !! orthogonal matrix X:
     !! [  I  0  0 |  0  0  0 ]
     !! [  0  C  0 |  0 -S  0 ]
     !! [ X11 | X12 ]   [ U1 |    ] [  0  0  0 |  0  0 -I ] [ V1 |    ]**T
     !! X = [-----------] = [---------] [---------------------] [---------]   .
     !! [ X21 | X22 ]   [    | U2 ] [  0  0  0 |  I  0  0 ] [    | V2 ]
     !! [  0  S  0 |  0  C  0 ]
     !! [  0  0  I |  0  0  0 ]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P,
     !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
     !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
     !! which R = MIN(P,M-P,Q,M-Q).
     ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, &
               work, lwork, iwork, 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) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, &
                     lwork, m, p, q
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(sp), intent(out) :: theta(*)
           real(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*)
                     
           real(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ===================================================================
           
           ! Local Arrays 
           real(sp) :: dummy(1_${ik}$)
           ! Local Scalars 
           character :: transt, signst
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, &
           lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, &
           lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, &
                     lworkopt
           logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           wantv2t = stdlib_lsame( jobv2t, 'Y' )
           colmajor = .not. stdlib_lsame( trans, 'T' )
           defaultsigns = .not. stdlib_lsame( signs, 'O' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -7_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -8_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -9_${ik}$
           else if ( colmajor .and.  ldx11 < max( 1_${ik}$, p ) ) then
             info = -11_${ik}$
           else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
             info = -11_${ik}$
           else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
             info = -13_${ik}$
           else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
             info = -13_${ik}$
           else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
             info = -15_${ik}$
           else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
             info = -15_${ik}$
           else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
             info = -17_${ik}$
           else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
             info = -17_${ik}$
           else if( wantu1 .and. ldu1 < p ) then
              info = -20_${ik}$
           else if( wantu2 .and. ldu2 < m-p ) then
              info = -22_${ik}$
           else if( wantv1t .and. ldv1t < q ) then
              info = -24_${ik}$
           else if( wantv2t .and. ldv2t < m-q ) then
              info = -26_${ik}$
           end if
           ! work with transpose if convenient
           if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then
              if( colmajor ) then
                 transt = 'T'
              else
                 transt = 'N'
              end if
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_sorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, &
              ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,&
                        u2, ldu2, work, lwork, iwork, info )
              return
           end if
           ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if
           ! convenient
           if( info == 0_${ik}$ .and. m-q < q ) then
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_sorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, &
              ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, &
                        v1t,ldv1t, work, lwork, iwork, info )
              return
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m - p )
              itauq2 = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_sorgqr( m-q, m-q, m-q, dummy, max(1_${ik}$,m-q), dummy, work, -1_${ik}$,childinfo )
                        
              lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorgqrworkmin = max( 1_${ik}$, m - q )
              iorglq = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_sorglq( m-q, m-q, m-q, dummy, max(1_${ik}$,m-q), dummy, work, -1_${ik}$,childinfo )
                        
              lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorglqworkmin = max( 1_${ik}$, m - q )
              iorbdb = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
                        ldx22, dummy, dummy, dummy, dummy, dummy,dummy,work,-1_${ik}$,childinfo )
              lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorbdbworkmin = lorbdbworkopt
              ib11d = itauq2 + max( 1_${ik}$, m - q )
              ib11e = ib11d + max( 1_${ik}$, q )
              ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, q )
              ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, q )
              ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, q )
              ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ )
              call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,dummy, dummy, u1, &
              ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, dummy, dummy, dummy, dummy, dummy, dummy,&
                        dummy, dummy, work, -1_${ik}$, childinfo )
              lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lbbcsdworkmin = lbbcsdworkopt
              lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$
              lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$
              work(1_${ik}$) = max(lworkopt,lworkmin)
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -22_${ik}$
              else
                 lorgqrwork = lwork - iorgqr + 1_${ik}$
                 lorglqwork = lwork - iorglq + 1_${ik}$
                 lorbdbwork = lwork - iorbdb + 1_${ik}$
                 lbbcsdwork = lwork - ibbcsd + 1_${ik}$
              end if
           end if
           ! abort if any illegal arguments
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORCSD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! transform to bidiagonal block form
           call stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, &
           ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(&
                     iorbdb), lorbdbwork, childinfo )
           ! accumulate householder reflectors
           if( colmajor ) then
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglqwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t )
                 call stdlib${ii}$_slacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), ldv2t )
                           
                 call stdlib${ii}$_sorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), &
                           lorglqwork, info )
              end if
           else
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', q, p, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_sorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_sorglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_sorgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), &
                           lorgqrwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t )
                 call stdlib${ii}$_slacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t )
                           
                 call stdlib${ii}$_sorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), &
                           lorgqrwork, info )
              end if
           end if
           ! compute the csd of the matrix in bidiagonal-block form
           call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,&
            ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(&
            ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, &
                      info )
           ! permute rows and columns to place identity submatrices in top-
           ! left corner of (1,1)-block and/or bottom-right corner of (1,2)-
           ! block and/or bottom-right corner of (2,1)-block and/or top-left
           ! corner of (2,2)-block
           if( q > 0_${ik}$ .and. wantu2 ) then
              do i = 1, q
                 iwork(i) = m - p - q + i
              end do
              do i = q + 1, m - p
                 iwork(i) = i - q
              end do
              if( colmajor ) then
                 call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork )
              else
                 call stdlib${ii}$_slapmr( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           end if
           if( m > 0_${ik}$ .and. wantv2t ) then
              do i = 1, p
                 iwork(i) = m - p - q + i
              end do
              do i = p + 1, m - q
                 iwork(i) = i - p
              end do
              if( .not. colmajor ) then
                 call stdlib${ii}$_slapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
              else
                 call stdlib${ii}$_slapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
              end if
           end if
           return
           ! end stdlib${ii}$_sorcsd
     end subroutine stdlib${ii}$_sorcsd

     recursive module subroutine stdlib${ii}$_dorcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, &
     !! DORCSD computes the CS decomposition of an M-by-M partitioned
     !! orthogonal matrix X:
     !! [  I  0  0 |  0  0  0 ]
     !! [  0  C  0 |  0 -S  0 ]
     !! [ X11 | X12 ]   [ U1 |    ] [  0  0  0 |  0  0 -I ] [ V1 |    ]**T
     !! X = [-----------] = [---------] [---------------------] [---------]   .
     !! [ X21 | X22 ]   [    | U2 ] [  0  0  0 |  I  0  0 ] [    | V2 ]
     !! [  0  S  0 |  0  C  0 ]
     !! [  0  0  I |  0  0  0 ]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P,
     !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
     !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
     !! which R = MIN(P,M-P,Q,M-Q).
     ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, &
               work, lwork, iwork, 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) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, &
                     lwork, m, p, q
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(dp), intent(out) :: theta(*)
           real(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*)
                     
           real(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ===================================================================
           
           ! Local Scalars 
           character :: transt, signst
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, &
           lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, &
           lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, &
                     lworkopt
           logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           wantv2t = stdlib_lsame( jobv2t, 'Y' )
           colmajor = .not. stdlib_lsame( trans, 'T' )
           defaultsigns = .not. stdlib_lsame( signs, 'O' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -7_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -8_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -9_${ik}$
           else if ( colmajor .and.  ldx11 < max( 1_${ik}$, p ) ) then
             info = -11_${ik}$
           else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
             info = -11_${ik}$
           else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
             info = -13_${ik}$
           else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
             info = -13_${ik}$
           else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
             info = -15_${ik}$
           else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
             info = -15_${ik}$
           else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
             info = -17_${ik}$
           else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
             info = -17_${ik}$
           else if( wantu1 .and. ldu1 < p ) then
              info = -20_${ik}$
           else if( wantu2 .and. ldu2 < m-p ) then
              info = -22_${ik}$
           else if( wantv1t .and. ldv1t < q ) then
              info = -24_${ik}$
           else if( wantv2t .and. ldv2t < m-q ) then
              info = -26_${ik}$
           end if
           ! work with transpose if convenient
           if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then
              if( colmajor ) then
                 transt = 'T'
              else
                 transt = 'N'
              end if
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_dorcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, &
              ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,&
                        u2, ldu2, work, lwork, iwork, info )
              return
           end if
           ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if
           ! convenient
           if( info == 0_${ik}$ .and. m-q < q ) then
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_dorcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, &
              ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, &
                        v1t,ldv1t, work, lwork, iwork, info )
              return
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m - p )
              itauq2 = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_dorgqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo )
              lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorgqrworkmin = max( 1_${ik}$, m - q )
              iorglq = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_dorglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo )
              lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorglqworkmin = max( 1_${ik}$, m - q )
              iorbdb = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
                        ldx22, theta, v1t, u1, u2, v1t,v2t, work, -1_${ik}$, childinfo )
              lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorbdbworkmin = lorbdbworkopt
              ib11d = itauq2 + max( 1_${ik}$, m - q )
              ib11e = ib11d + max( 1_${ik}$, q )
              ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, q )
              ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, q )
              ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, q )
              ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ )
              call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, &
              ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, u1, u1, u1, u1, u1, u1, u1, u1, work, -1_${ik}$,&
                        childinfo )
              lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lbbcsdworkmin = lbbcsdworkopt
              lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$
              lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$
              work(1_${ik}$) = max(lworkopt,lworkmin)
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -22_${ik}$
              else
                 lorgqrwork = lwork - iorgqr + 1_${ik}$
                 lorglqwork = lwork - iorglq + 1_${ik}$
                 lorbdbwork = lwork - iorbdb + 1_${ik}$
                 lbbcsdwork = lwork - ibbcsd + 1_${ik}$
              end if
           end if
           ! abort if any illegal arguments
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORCSD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! transform to bidiagonal block form
           call stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, &
           ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(&
                     iorbdb), lorbdbwork, childinfo )
           ! accumulate householder reflectors
           if( colmajor ) then
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglqwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t )
                 if (m-p > q) then
                    call stdlib${ii}$_dlacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), &
                              ldv2t )
                 end if
                 if (m > q) then
                    call stdlib${ii}$_dorglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), &
                              lorglqwork, info )
                 end if
              end if
           else
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', q, p, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_dorglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_dorglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_dorgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), &
                           lorgqrwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t )
                 call stdlib${ii}$_dlacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t )
                           
                 call stdlib${ii}$_dorgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), &
                           lorgqrwork, info )
              end if
           end if
           ! compute the csd of the matrix in bidiagonal-block form
           call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,&
            ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(&
            ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, &
                      info )
           ! permute rows and columns to place identity submatrices in top-
           ! left corner of (1,1)-block and/or bottom-right corner of (1,2)-
           ! block and/or bottom-right corner of (2,1)-block and/or top-left
           ! corner of (2,2)-block
           if( q > 0_${ik}$ .and. wantu2 ) then
              do i = 1, q
                 iwork(i) = m - p - q + i
              end do
              do i = q + 1, m - p
                 iwork(i) = i - q
              end do
              if( colmajor ) then
                 call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
              else
                 call stdlib${ii}$_dlapmr( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           end if
           if( m > 0_${ik}$ .and. wantv2t ) then
              do i = 1, p
                 iwork(i) = m - p - q + i
              end do
              do i = p + 1, m - q
                 iwork(i) = i - p
              end do
              if( .not. colmajor ) then
                 call stdlib${ii}$_dlapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
              else
                 call stdlib${ii}$_dlapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
              end if
           end if
           return
           ! end stdlib${ii}$_dorcsd
     end subroutine stdlib${ii}$_dorcsd

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     recursive module subroutine stdlib${ii}$_${ri}$orcsd( jobu1, jobu2, jobv1t, jobv2t, trans,signs, m, p, q, x11, &
     !! DORCSD: computes the CS decomposition of an M-by-M partitioned
     !! orthogonal matrix X:
     !! [  I  0  0 |  0  0  0 ]
     !! [  0  C  0 |  0 -S  0 ]
     !! [ X11 | X12 ]   [ U1 |    ] [  0  0  0 |  0  0 -I ] [ V1 |    ]**T
     !! X = [-----------] = [---------] [---------------------] [---------]   .
     !! [ X21 | X22 ]   [    | U2 ] [  0  0  0 |  I  0  0 ] [    | V2 ]
     !! [  0  S  0 |  0  C  0 ]
     !! [  0  0  I |  0  0  0 ]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, V1, and V2 are P-by-P,
     !! (M-P)-by-(M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. C and S are
     !! R-by-R nonnegative diagonal matrices satisfying C^2 + S^2 = I, in
     !! which R = MIN(P,M-P,Q,M-Q).
     ldx11, x12,ldx12, x21, ldx21, x22, ldx22, theta,u1, ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, &
               work, lwork, iwork, 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) :: jobu1, jobu2, jobv1t, jobv2t, signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, ldv2t, ldx11, ldx12, ldx21, ldx22, &
                     lwork, m, p, q
           ! Array Arguments 
           integer(${ik}$), intent(out) :: iwork(*)
           real(${rk}$), intent(out) :: theta(*)
           real(${rk}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), v2t(ldv2t,*), work(*)
                     
           real(${rk}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ===================================================================
           
           ! Local Scalars 
           character :: transt, signst
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, itauq2, j, lbbcsdwork, &
           lbbcsdworkmin, lbbcsdworkopt, lorbdbwork, lorbdbworkmin, lorbdbworkopt, lorglqwork, &
           lorglqworkmin, lorglqworkopt, lorgqrwork, lorgqrworkmin, lorgqrworkopt, lworkmin, &
                     lworkopt
           logical(lk) :: colmajor, defaultsigns, lquery, wantu1, wantu2, wantv1t, wantv2t
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           wantv2t = stdlib_lsame( jobv2t, 'Y' )
           colmajor = .not. stdlib_lsame( trans, 'T' )
           defaultsigns = .not. stdlib_lsame( signs, 'O' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -7_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -8_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -9_${ik}$
           else if ( colmajor .and.  ldx11 < max( 1_${ik}$, p ) ) then
             info = -11_${ik}$
           else if (.not. colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
             info = -11_${ik}$
           else if (colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
             info = -13_${ik}$
           else if (.not. colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
             info = -13_${ik}$
           else if (colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
             info = -15_${ik}$
           else if (.not. colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
             info = -15_${ik}$
           else if (colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
             info = -17_${ik}$
           else if (.not. colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
             info = -17_${ik}$
           else if( wantu1 .and. ldu1 < p ) then
              info = -20_${ik}$
           else if( wantu2 .and. ldu2 < m-p ) then
              info = -22_${ik}$
           else if( wantv1t .and. ldv1t < q ) then
              info = -24_${ik}$
           else if( wantv2t .and. ldv2t < m-q ) then
              info = -26_${ik}$
           end if
           ! work with transpose if convenient
           if( info == 0_${ik}$ .and. min( p, m-p ) < min( q, m-q ) ) then
              if( colmajor ) then
                 transt = 'T'
              else
                 transt = 'N'
              end if
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_${ri}$orcsd( jobv1t, jobv2t, jobu1, jobu2, transt, signst, m,q, p, x11, &
              ldx11, x21, ldx21, x12, ldx12, x22,ldx22, theta, v1t, ldv1t, v2t, ldv2t, u1, ldu1,&
                        u2, ldu2, work, lwork, iwork, info )
              return
           end if
           ! work with permutation [ 0 i; i 0 ] * x * [ 0 i; i 0 ] if
           ! convenient
           if( info == 0_${ik}$ .and. m-q < q ) then
              if( defaultsigns ) then
                 signst = 'O'
              else
                 signst = 'D'
              end if
              call stdlib${ii}$_${ri}$orcsd( jobu2, jobu1, jobv2t, jobv1t, trans, signst, m,m-p, m-q, x22, &
              ldx22, x21, ldx21, x12, ldx12, x11,ldx11, theta, u2, ldu2, u1, ldu1, v2t, ldv2t, &
                        v1t,ldv1t, work, lwork, iwork, info )
              return
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              itaup1 = iphi + max( 1_${ik}$, q - 1_${ik}$ )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m - p )
              itauq2 = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_${ri}$orgqr( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo )
              lorgqrworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorgqrworkmin = max( 1_${ik}$, m - q )
              iorglq = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_${ri}$orglq( m-q, m-q, m-q, u1, max(1_${ik}$,m-q), u1, work, -1_${ik}$,childinfo )
              lorglqworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorglqworkmin = max( 1_${ik}$, m - q )
              iorbdb = itauq2 + max( 1_${ik}$, m - q )
              call stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
                        ldx22, theta, v1t, u1, u2, v1t,v2t, work, -1_${ik}$, childinfo )
              lorbdbworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lorbdbworkmin = lorbdbworkopt
              ib11d = itauq2 + max( 1_${ik}$, m - q )
              ib11e = ib11d + max( 1_${ik}$, q )
              ib12d = ib11e + max( 1_${ik}$, q - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, q )
              ib21d = ib12e + max( 1_${ik}$, q - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, q )
              ib22d = ib21e + max( 1_${ik}$, q - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, q )
              ibbcsd = ib22e + max( 1_${ik}$, q - 1_${ik}$ )
              call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q,theta, theta, u1, &
              ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, u1, u1, u1, u1, u1, u1, u1, u1, work, -1_${ik}$,&
                        childinfo )
              lbbcsdworkopt = int( work(1_${ik}$),KIND=${ik}$)
              lbbcsdworkmin = lbbcsdworkopt
              lworkopt = max( iorgqr + lorgqrworkopt, iorglq + lorglqworkopt,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkopt ) - 1_${ik}$
              lworkmin = max( iorgqr + lorgqrworkmin, iorglq + lorglqworkmin,iorbdb + &
                        lorbdbworkopt, ibbcsd + lbbcsdworkmin ) - 1_${ik}$
              work(1_${ik}$) = max(lworkopt,lworkmin)
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -22_${ik}$
              else
                 lorgqrwork = lwork - iorgqr + 1_${ik}$
                 lorglqwork = lwork - iorglq + 1_${ik}$
                 lorbdbwork = lwork - iorbdb + 1_${ik}$
                 lbbcsdwork = lwork - ibbcsd + 1_${ik}$
              end if
           end if
           ! abort if any illegal arguments
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORCSD', -info )
              return
           else if( lquery ) then
              return
           end if
           ! transform to bidiagonal block form
           call stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12, x21,ldx21, x22, &
           ldx22, theta, work(iphi), work(itaup1),work(itaup2), work(itauq1), work(itauq2),work(&
                     iorbdb), lorbdbwork, childinfo )
           ! accumulate householder reflectors
           if( colmajor ) then
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqrwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqrwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', q-1, q-1, x11(1_${ik}$,2_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglqwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', p, m-q, x12, ldx12, v2t, ldv2t )
                 if (m-p > q) then
                    call stdlib${ii}$_${ri}$lacpy( 'U', m-p-q, m-p-q, x22(q+1,p+1), ldx22,v2t(p+1,p+1), &
                              ldv2t )
                 end if
                 if (m > q) then
                    call stdlib${ii}$_${ri}$orglq( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorglq), &
                              lorglqwork, info )
                 end if
              end if
           else
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', q, p, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_${ri}$orglq( p, p, q, u1, ldu1, work(itaup1), work(iorglq),lorglqwork, &
                           info)
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', q, m-p, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_${ri}$orglq( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorglq), lorglqwork,&
                            info )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', q-1, q-1, x11(2_${ik}$,1_${ik}$), ldx11, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 v1t(1_${ik}$, 1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_${ri}$orgqr( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorgqr), &
                           lorgqrwork, info )
              end if
              if( wantv2t .and. m-q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-q, p, x12, ldx12, v2t, ldv2t )
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p-q, m-p-q, x22(p+1,q+1), ldx22,v2t(p+1,p+1), ldv2t )
                           
                 call stdlib${ii}$_${ri}$orgqr( m-q, m-q, m-q, v2t, ldv2t, work(itauq2),work(iorgqr), &
                           lorgqrwork, info )
              end if
           end if
           ! compute the csd of the matrix in bidiagonal-block form
           call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, jobv2t, trans, m, p, q, theta,work(iphi), u1,&
            ldu1, u2, ldu2, v1t, ldv1t, v2t,ldv2t, work(ib11d), work(ib11e), work(ib12d),work(&
            ib12e), work(ib21d), work(ib21e), work(ib22d),work(ib22e), work(ibbcsd), lbbcsdwork, &
                      info )
           ! permute rows and columns to place identity submatrices in top-
           ! left corner of (1,1)-block and/or bottom-right corner of (1,2)-
           ! block and/or bottom-right corner of (2,1)-block and/or top-left
           ! corner of (2,2)-block
           if( q > 0_${ik}$ .and. wantu2 ) then
              do i = 1, q
                 iwork(i) = m - p - q + i
              end do
              do i = q + 1, m - p
                 iwork(i) = i - q
              end do
              if( colmajor ) then
                 call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork )
              else
                 call stdlib${ii}$_${ri}$lapmr( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           end if
           if( m > 0_${ik}$ .and. wantv2t ) then
              do i = 1, p
                 iwork(i) = m - p - q + i
              end do
              do i = p + 1, m - q
                 iwork(i) = i - p
              end do
              if( .not. colmajor ) then
                 call stdlib${ii}$_${ri}$lapmt( .false., m-q, m-q, v2t, ldv2t, iwork )
              else
                 call stdlib${ii}$_${ri}$lapmr( .false., m-q, m-q, v2t, ldv2t, iwork )
              end if
           end if
           return
           ! end stdlib${ii}$_${ri}$orcsd
     end subroutine stdlib${ii}$_${ri}$orcsd

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, &
     !! SORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with
     !! orthonormal columns that has been partitioned into a 2-by-1 block
     !! structure:
     !! [  I1 0  0 ]
     !! [  0  C  0 ]
     !! [ X11 ]   [ U1 |    ] [  0  0  0 ]
     !! X = [-----] = [---------] [----------] V1**T .
     !! [ X21 ]   [    | U2 ] [  0  0  0 ]
     !! [  0  S  0 ]
     !! [  0  0  I2]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P,
     !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R
     !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which
     !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a
     !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0).
               u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, 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) :: jobu1, jobu2, jobv1t
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q
           ! Array Arguments 
           real(sp), intent(out) :: theta(*)
           real(sp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
           integer(${ik}$), intent(out) :: iwork(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, &
           lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, &
                     r
           logical(lk) :: lquery, wantu1, wantu2, wantv1t
           ! Local Arrays 
           real(sp) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$)
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -4_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -5_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -6_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -8_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -10_${ik}$
           else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then
              info = -13_${ik}$
           else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then
              info = -15_${ik}$
           else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then
              info = -17_${ik}$
           end if
           r = min( p, m-p, q, m-q )
           ! compute workspace
             ! work layout:
           ! |-------------------------------------------------------|
           ! | lworkopt (1)                                          |
           ! |-------------------------------------------------------|
           ! | phi (max(1,r-1))                                      |
           ! |-------------------------------------------------------|
           ! | taup1 (max(1,p))                        | b11d (r)    |
           ! | taup2 (max(1,m-p))                      | b11e (r-1)  |
           ! | tauq1 (max(1,q))                        | b12d (r)    |
           ! |-----------------------------------------| b12e (r-1)  |
           ! | stdlib${ii}$_sorbdb work | stdlib${ii}$_sorgqr work | stdlib${ii}$_sorglq work | b21d (r)    |
           ! |             |             |             | b21e (r-1)  |
           ! |             |             |             | b22d (r)    |
           ! |             |             |             | b22e (r-1)  |
           ! |             |             |             | stdlib${ii}$_sbbcsd work |
           ! |-------------------------------------------------------|
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              ib11d = iphi + max( 1_${ik}$, r-1 )
              ib11e = ib11d + max( 1_${ik}$, r )
              ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, r )
              ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, r )
              ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, r )
              ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ )
              itaup1 = iphi + max( 1_${ik}$, r-1 )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m-p )
              iorbdb = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq1 + max( 1_${ik}$, q )
              iorglq = itauq1 + max( 1_${ik}$, q )
              lorgqrmin = 1_${ik}$
              lorgqropt = 1_${ik}$
              lorglqmin = 1_${ik}$
              lorglqopt = 1_${ik}$
              if( r == q ) then
                 call stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, work, -1_${ik}$,childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 endif
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                              
                    lorglqmin = max( lorglqmin, q-1 )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, &
                 ldu1, u2, ldu2, v1t, ldv1t, dum2,1_${ik}$, dum1, dum1, dum1, dum1, dum1,dum1, dum1, &
                           dum1, work(1_${ik}$), -1_${ik}$, childinfo)
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == p ) then
                 call stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo &
                              )
                    lorgqrmin = max( lorgqrmin, p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_sbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, &
                 ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, dum1, dum1, dum1, dum1, dum1,dum1, dum1, dum1,&
                            work(1_${ik}$), -1_${ik}$, childinfo)
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == m-p ) then
                 call stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2, dum1,work(1_${ik}$), -1_${ik}$, &
                              childinfo )
                    lorgqrmin = max( lorgqrmin, m-p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_sbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, &
                 dum2, 1_${ik}$, v1t, ldv1t, u2, ldu2,u1, ldu1, dum1, dum1, dum1, dum1,dum1, dum1, dum1, &
                           dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else
                 call stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, dum1,work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = m + int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_sorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_sorglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_sbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, &
                 ldu2, u1, ldu1, dum2, 1_${ik}$,v1t, ldv1t, dum1, dum1, dum1, dum1,dum1, dum1, dum1, &
                           dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              end if
              lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                 info = -19_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORCSD2BY1', -info )
              return
           else if( lquery ) then
              return
           end if
           lorgqr = lwork-iorgqr+1
           lorglq = lwork-iorglq+1
           ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q,
           ! in which r = min(p,m-p,q,m-q)
           if( r == q ) then
              ! case 1: r = q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 v1t(1_${ik}$,1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_slacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 call stdlib${ii}$_sorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglq, childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_sbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, &
              ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e), work(ib12d),work(&
              ib12e), work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,&
                        childinfo )
              ! permute rows and columns to place zero submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == p ) then
              ! case 2: r = p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 u1(1_${ik}$,1_${ik}$) = one
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                    u1(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_slacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 )
                 call stdlib${ii}$_sorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), &
                           lorgqr, childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_sorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', p, q, x11, ldx11, v1t, ldv1t )
                 call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_sbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, &
              ldv1t, dum1, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)&
              , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo &
                        )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_slapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == m-p ) then
              ! case 3: r = m-p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_sorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 u2(1_${ik}$,1_${ik}$) = one
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                    u2(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_slacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_sorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)&
                           , lorgqr, childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_sorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_sbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), &
              dum1, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > r ) then
                 do i = 1, r
                    iwork(i) = q - r + i
                 end do
                 do i = r + 1, q
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_slapmt( .false., p, q, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_slapmr( .false., q, q, v1t, ldv1t, iwork )
                 end if
              end if
           else
              ! case 4: r = m-q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
              , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo )
                        
              ! accumulate householder reflectors
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_scopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ )
              end if
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_scopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ )
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_slacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 )
                 call stdlib${ii}$_sorgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_slacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_sorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_slacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_slacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+&
                           1_${ik}$), ldv1t )
                 call stdlib${ii}$_slacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t )
                           
                 call stdlib${ii}$_sorglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_sbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), &
              u2, ldu2, u1, ldu1, dum1, 1_${ik}$,v1t, ldv1t, work(ib11d), work(ib11e), work(ib12d),work(&
              ib12e), work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,&
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( p > r ) then
                 do i = 1, r
                    iwork(i) = p - r + i
                 end do
                 do i = r + 1, p
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_slapmt( .false., p, p, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_slapmr( .false., p, q, v1t, ldv1t, iwork )
                 end if
              end if
           end if
           return
     end subroutine stdlib${ii}$_sorcsd2by1

     module subroutine stdlib${ii}$_dorcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, &
     !! DORCSD2BY1 computes the CS decomposition of an M-by-Q matrix X with
     !! orthonormal columns that has been partitioned into a 2-by-1 block
     !! structure:
     !! [  I1 0  0 ]
     !! [  0  C  0 ]
     !! [ X11 ]   [ U1 |    ] [  0  0  0 ]
     !! X = [-----] = [---------] [----------] V1**T .
     !! [ X21 ]   [    | U2 ] [  0  0  0 ]
     !! [  0  S  0 ]
     !! [  0  0  I2]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P,
     !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R
     !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which
     !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a
     !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0).
               u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info )
        ! -- lapack computational routine (3.5.0_dp) --
        ! -- 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) :: jobu1, jobu2, jobv1t
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q
           ! Array Arguments 
           real(dp), intent(out) :: theta(*)
           real(dp), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
           integer(${ik}$), intent(out) :: iwork(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, &
           lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, &
                     r
           logical(lk) :: lquery, wantu1, wantu2, wantv1t
           ! Local Arrays 
           real(dp) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$)
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -4_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -5_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -6_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -8_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -10_${ik}$
           else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then
              info = -13_${ik}$
           else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then
              info = -15_${ik}$
           else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then
              info = -17_${ik}$
           end if
           r = min( p, m-p, q, m-q )
           ! compute workspace
             ! work layout:
           ! |-------------------------------------------------------|
           ! | lworkopt (1)                                          |
           ! |-------------------------------------------------------|
           ! | phi (max(1,r-1))                                      |
           ! |-------------------------------------------------------|
           ! | taup1 (max(1,p))                        | b11d (r)    |
           ! | taup2 (max(1,m-p))                      | b11e (r-1)  |
           ! | tauq1 (max(1,q))                        | b12d (r)    |
           ! |-----------------------------------------| b12e (r-1)  |
           ! | stdlib${ii}$_dorbdb work | stdlib${ii}$_dorgqr work | stdlib${ii}$_dorglq work | b21d (r)    |
           ! |             |             |             | b21e (r-1)  |
           ! |             |             |             | b22d (r)    |
           ! |             |             |             | b22e (r-1)  |
           ! |             |             |             | stdlib${ii}$_dbbcsd work |
           ! |-------------------------------------------------------|
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              ib11d = iphi + max( 1_${ik}$, r-1 )
              ib11e = ib11d + max( 1_${ik}$, r )
              ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, r )
              ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, r )
              ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, r )
              ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ )
              itaup1 = iphi + max( 1_${ik}$, r-1 )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m-p )
              iorbdb = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq1 + max( 1_${ik}$, q )
              iorglq = itauq1 + max( 1_${ik}$, q )
              lorgqrmin = 1_${ik}$
              lorgqropt = 1_${ik}$
              lorglqmin = 1_${ik}$
              lorglqopt = 1_${ik}$
              if( r == q ) then
                 call stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, work,-1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 endif
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                              
                    lorglqmin = max( lorglqmin, q-1 )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, &
                 ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,&
                            work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == p ) then
                 call stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo &
                              )
                    lorgqrmin = max( lorgqrmin, p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_dbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, &
                 ldv1t, dum2, 1_${ik}$, u1, ldu1,u2, ldu2, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1, &
                           work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == m-p ) then
                 call stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,dum1, work(1_${ik}$), -1_${ik}$, &
                              childinfo )
                    lorgqrmin = max( lorgqrmin, m-p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_dbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, &
                 dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, dum1, dum1, dum1,dum1, dum1, dum1, dum1,&
                           dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else
                 call stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = m + int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_dorglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_dbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, &
                 ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,&
                            work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              end if
              lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                 info = -19_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORCSD2BY1', -info )
              return
           else if( lquery ) then
              return
           end if
           lorgqr = lwork-iorgqr+1
           lorglq = lwork-iorglq+1
           ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q,
           ! in which r = min(p,m-p,q,m-q)
           if( r == q ) then
              ! case 1: r = q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 v1t(1_${ik}$,1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_dlacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 call stdlib${ii}$_dorglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglq, childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_dbbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, &
              ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place zero submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == p ) then
              ! case 2: r = p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 u1(1_${ik}$,1_${ik}$) = one
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                    u1(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_dlacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 )
                 call stdlib${ii}$_dorgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), &
                           lorgqr, childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', p, q, x11, ldx11, v1t, ldv1t )
                 call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_dbbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, &
              ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)&
              , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo &
                        )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == m-p ) then
              ! case 3: r = m-p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 u2(1_${ik}$,1_${ik}$) = one
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                    u2(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_dlacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_dorgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)&
                           , lorgqr, childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_dorglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_dbbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), &
              dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > r ) then
                 do i = 1, r
                    iwork(i) = q - r + i
                 end do
                 do i = r + 1, q
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_dlapmt( .false., p, q, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_dlapmr( .false., q, q, v1t, ldv1t, iwork )
                 end if
              end if
           else
              ! case 4: r = m-q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
              , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo )
                        
              ! accumulate householder reflectors
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_dcopy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ )
              end if
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_dcopy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ )
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_dlacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 )
                 call stdlib${ii}$_dorgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_dlacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_dlacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_dlacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+&
                           1_${ik}$), ldv1t )
                 call stdlib${ii}$_dlacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t )
                           
                 call stdlib${ii}$_dorglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_dbbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), &
              u2, ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( p > r ) then
                 do i = 1, r
                    iwork(i) = p - r + i
                 end do
                 do i = r + 1, p
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_dlapmt( .false., p, p, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_dlapmr( .false., p, q, v1t, ldv1t, iwork )
                 end if
              end if
           end if
           return
     end subroutine stdlib${ii}$_dorcsd2by1

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orcsd2by1( jobu1, jobu2, jobv1t, m, p, q, x11, ldx11,x21, ldx21, theta, &
     !! DORCSD2BY1: computes the CS decomposition of an M-by-Q matrix X with
     !! orthonormal columns that has been partitioned into a 2-by-1 block
     !! structure:
     !! [  I1 0  0 ]
     !! [  0  C  0 ]
     !! [ X11 ]   [ U1 |    ] [  0  0  0 ]
     !! X = [-----] = [---------] [----------] V1**T .
     !! [ X21 ]   [    | U2 ] [  0  0  0 ]
     !! [  0  S  0 ]
     !! [  0  0  I2]
     !! X11 is P-by-Q. The orthogonal matrices U1, U2, and V1 are P-by-P,
     !! (M-P)-by-(M-P), and Q-by-Q, respectively. C and S are R-by-R
     !! nonnegative diagonal matrices satisfying C^2 + S^2 = I, in which
     !! R = MIN(P,M-P,Q,M-Q). I1 is a K1-by-K1 identity matrix and I2 is a
     !! K2-by-K2 identity matrix, where K1 = MAX(Q+P-M,0), K2 = MAX(Q-P,0).
               u1, ldu1, u2, ldu2, v1t,ldv1t, work, lwork, iwork, info )
        ! -- lapack computational routine (3.5.0_${rk}$) --
        ! -- 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) :: jobu1, jobu2, jobv1t
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldu1, ldu2, ldv1t, lwork, ldx11, ldx21, m, p, q
           ! Array Arguments 
           real(${rk}$), intent(out) :: theta(*)
           real(${rk}$), intent(out) :: u1(ldu1,*), u2(ldu2,*), v1t(ldv1t,*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
           integer(${ik}$), intent(out) :: iwork(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, ib11d, ib11e, ib12d, ib12e, ib21d, ib21e, ib22d, ib22e, &
           ibbcsd, iorbdb, iorglq, iorgqr, iphi, itaup1, itaup2, itauq1, j, lbbcsd, lorbdb, &
           lorglq, lorglqmin, lorglqopt, lorgqr, lorgqrmin, lorgqropt, lworkmin, lworkopt, &
                     r
           logical(lk) :: lquery, wantu1, wantu2, wantv1t
           ! Local Arrays 
           real(${rk}$) :: dum1(1_${ik}$), dum2(1_${ik}$,1_${ik}$)
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           wantu1 = stdlib_lsame( jobu1, 'Y' )
           wantu2 = stdlib_lsame( jobu2, 'Y' )
           wantv1t = stdlib_lsame( jobv1t, 'Y' )
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -4_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -5_${ik}$
           else if( q < 0_${ik}$ .or. q > m ) then
              info = -6_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -8_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -10_${ik}$
           else if( wantu1 .and. ldu1 < max( 1_${ik}$, p ) ) then
              info = -13_${ik}$
           else if( wantu2 .and. ldu2 < max( 1_${ik}$, m - p ) ) then
              info = -15_${ik}$
           else if( wantv1t .and. ldv1t < max( 1_${ik}$, q ) ) then
              info = -17_${ik}$
           end if
           r = min( p, m-p, q, m-q )
           ! compute workspace
             ! work layout:
           ! |-------------------------------------------------------|
           ! | lworkopt (1)                                          |
           ! |-------------------------------------------------------|
           ! | phi (max(1,r-1))                                      |
           ! |-------------------------------------------------------|
           ! | taup1 (max(1,p))                        | b11d (r)    |
           ! | taup2 (max(1,m-p))                      | b11e (r-1)  |
           ! | tauq1 (max(1,q))                        | b12d (r)    |
           ! |-----------------------------------------| b12e (r-1)  |
           ! | stdlib${ii}$_${ri}$orbdb work | stdlib${ii}$_${ri}$orgqr work | stdlib${ii}$_${ri}$orglq work | b21d (r)    |
           ! |             |             |             | b21e (r-1)  |
           ! |             |             |             | b22d (r)    |
           ! |             |             |             | b22e (r-1)  |
           ! |             |             |             | stdlib${ii}$_${ri}$bbcsd work |
           ! |-------------------------------------------------------|
           if( info == 0_${ik}$ ) then
              iphi = 2_${ik}$
              ib11d = iphi + max( 1_${ik}$, r-1 )
              ib11e = ib11d + max( 1_${ik}$, r )
              ib12d = ib11e + max( 1_${ik}$, r - 1_${ik}$ )
              ib12e = ib12d + max( 1_${ik}$, r )
              ib21d = ib12e + max( 1_${ik}$, r - 1_${ik}$ )
              ib21e = ib21d + max( 1_${ik}$, r )
              ib22d = ib21e + max( 1_${ik}$, r - 1_${ik}$ )
              ib22e = ib22d + max( 1_${ik}$, r )
              ibbcsd = ib22e + max( 1_${ik}$, r - 1_${ik}$ )
              itaup1 = iphi + max( 1_${ik}$, r-1 )
              itaup2 = itaup1 + max( 1_${ik}$, p )
              itauq1 = itaup2 + max( 1_${ik}$, m-p )
              iorbdb = itauq1 + max( 1_${ik}$, q )
              iorgqr = itauq1 + max( 1_${ik}$, q )
              iorglq = itauq1 + max( 1_${ik}$, q )
              lorgqrmin = 1_${ik}$
              lorgqropt = 1_${ik}$
              lorglqmin = 1_${ik}$
              lorglqopt = 1_${ik}$
              if( r == q ) then
                 call stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1, work,-1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 endif
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t, ldv1t,dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                              
                    lorglqmin = max( lorglqmin, q-1 )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,dum1, u1, &
                 ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,&
                            work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == p ) then
                 call stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, dum1,work(1_${ik}$), -1_${ik}$, childinfo &
                              )
                    lorgqrmin = max( lorgqrmin, p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_${ri}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,dum1, v1t, &
                 ldv1t, dum2, 1_${ik}$, u1, ldu1,u2, ldu2, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1, &
                           work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else if( r == m-p ) then
                 call stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,dum1, work(1_${ik}$), -1_${ik}$, &
                              childinfo )
                    lorgqrmin = max( lorgqrmin, m-p-1 )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_${ri}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, dum1, &
                 dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, dum1, dum1, dum1,dum1, dum1, dum1, dum1,&
                           dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              else
                 call stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,dum1, dum1, dum1, &
                           dum1,dum1, work(1_${ik}$), -1_${ik}$, childinfo )
                 lorbdb = m + int( work(1_${ik}$),KIND=${ik}$)
                 if( wantu1 .and. p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( p, p, m-q, u1, ldu1, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorgqrmin = max( lorgqrmin, p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantu2 .and. m-p > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1_${ik}$),-1_${ik}$, childinfo )
                              
                    lorgqrmin = max( lorgqrmin, m-p )
                    lorgqropt = max( lorgqropt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 if( wantv1t .and. q > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$orglq( q, q, q, v1t, ldv1t, dum1, work(1_${ik}$), -1_${ik}$,childinfo )
                    lorglqmin = max( lorglqmin, q )
                    lorglqopt = max( lorglqopt, int( work(1_${ik}$),KIND=${ik}$) )
                 end if
                 call stdlib${ii}$_${ri}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, dum1, u2, &
                 ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, dum1, dum1, dum1,dum1, dum1, dum1, dum1,dum1,&
                            work(1_${ik}$), -1_${ik}$, childinfo )
                 lbbcsd = int( work(1_${ik}$),KIND=${ik}$)
              end if
              lworkmin = max( iorbdb+lorbdb-1,iorgqr+lorgqrmin-1,iorglq+lorglqmin-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              lworkopt = max( iorbdb+lorbdb-1,iorgqr+lorgqropt-1,iorglq+lorglqopt-1,ibbcsd+lbbcsd-&
                        1_${ik}$ )
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                 info = -19_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORCSD2BY1', -info )
              return
           else if( lquery ) then
              return
           end if
           lorgqr = lwork-iorgqr+1
           lorglq = lwork-iorglq+1
           ! handle four cases separately: r = q, r = p, r = m-p, and r = m-q,
           ! in which r = min(p,m-p,q,m-q)
           if( r == q ) then
              ! case 1: r = q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 v1t(1_${ik}$,1_${ik}$) = one
                 do j = 2, q
                    v1t(1_${ik}$,j) = zero
                    v1t(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_${ri}$lacpy( 'U', q-1, q-1, x21(1_${ik}$,2_${ik}$), ldx21, v1t(2_${ik}$,2_${ik}$),ldv1t )
                 call stdlib${ii}$_${ri}$orglq( q-1, q-1, q-1, v1t(2_${ik}$,2_${ik}$), ldv1t, work(itauq1),work(iorglq), &
                           lorglq, childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_${ri}$bbcsd( jobu1, jobu2, jobv1t, 'N', 'N', m, p, q, theta,work(iphi), u1, &
              ldu1, u2, ldu2, v1t, ldv1t,dum2, 1_${ik}$, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place zero submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == p ) then
              ! case 2: r = p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 u1(1_${ik}$,1_${ik}$) = one
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                    u1(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_${ri}$lacpy( 'L', p-1, p-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$), ldu1 )
                 call stdlib${ii}$_${ri}$orgqr( p-1, p-1, p-1, u1(2_${ik}$,2_${ik}$), ldu1, work(itaup1),work(iorgqr), &
                           lorgqr, childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p, q, x21, ldx21, u2, ldu2 )
                 call stdlib${ii}$_${ri}$orgqr( m-p, m-p, q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', p, q, x11, ldx11, v1t, ldv1t )
                 call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_${ri}$bbcsd( jobv1t, 'N', jobu1, jobu2, 'T', m, q, p, theta,work(iphi), v1t, &
              ldv1t, dum2, 1_${ik}$, u1, ldu1, u2,ldu2, work(ib11d), work(ib11e), work(ib12d),work(ib12e)&
              , work(ib21d), work(ib21e),work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,childinfo &
                        )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > 0_${ik}$ .and. wantu2 ) then
                 do i = 1, q
                    iwork(i) = m - p - q + i
                 end do
                 do i = q + 1, m - p
                    iwork(i) = i - q
                 end do
                 call stdlib${ii}$_${ri}$lapmt( .false., m-p, m-p, u2, ldu2, iwork )
              end if
           else if( r == m-p ) then
              ! case 3: r = m-p
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
                        , work(itaup2),work(itauq1), work(iorbdb), lorbdb, childinfo )
              ! accumulate householder reflectors
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'L', p, q, x11, ldx11, u1, ldu1 )
                 call stdlib${ii}$_${ri}$orgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 u2(1_${ik}$,1_${ik}$) = one
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                    u2(j,1_${ik}$) = zero
                 end do
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p-1, m-p-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_${ri}$orgqr( m-p-1, m-p-1, m-p-1, u2(2_${ik}$,2_${ik}$), ldu2,work(itaup2), work(iorgqr)&
                           , lorgqr, childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', m-p, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_${ri}$orglq( q, q, r, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_${ri}$bbcsd( 'N', jobv1t, jobu2, jobu1, 'T', m, m-q, m-p,theta, work(iphi), &
              dum2, 1_${ik}$, v1t, ldv1t, u2,ldu2, u1, ldu1, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( q > r ) then
                 do i = 1, r
                    iwork(i) = q - r + i
                 end do
                 do i = r + 1, q
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_${ri}$lapmt( .false., p, q, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_${ri}$lapmr( .false., q, q, v1t, ldv1t, iwork )
                 end if
              end if
           else
              ! case 4: r = m-q
              ! simultaneously bidiagonalize x11 and x21
              call stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,work(iphi), work(itaup1)&
              , work(itaup2),work(itauq1), work(iorbdb), work(iorbdb+m),lorbdb-m, childinfo )
                        
              ! accumulate householder reflectors
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$copy( m-p, work(iorbdb+p), 1_${ik}$, u2, 1_${ik}$ )
              end if
              if( wantu1 .and. p > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$copy( p, work(iorbdb), 1_${ik}$, u1, 1_${ik}$ )
                 do j = 2, p
                    u1(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_${ri}$lacpy( 'L', p-1, m-q-1, x11(2_${ik}$,1_${ik}$), ldx11, u1(2_${ik}$,2_${ik}$),ldu1 )
                 call stdlib${ii}$_${ri}$orgqr( p, p, m-q, u1, ldu1, work(itaup1),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantu2 .and. m-p > 0_${ik}$ ) then
                 do j = 2, m-p
                    u2(1_${ik}$,j) = zero
                 end do
                 call stdlib${ii}$_${ri}$lacpy( 'L', m-p-1, m-q-1, x21(2_${ik}$,1_${ik}$), ldx21, u2(2_${ik}$,2_${ik}$),ldu2 )
                 call stdlib${ii}$_${ri}$orgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),work(iorgqr), lorgqr, &
                           childinfo )
              end if
              if( wantv1t .and. q > 0_${ik}$ ) then
                 call stdlib${ii}$_${ri}$lacpy( 'U', m-q, q, x21, ldx21, v1t, ldv1t )
                 call stdlib${ii}$_${ri}$lacpy( 'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,v1t(m-q+1,m-q+&
                           1_${ik}$), ldv1t )
                 call stdlib${ii}$_${ri}$lacpy( 'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,v1t(p+1,p+1), ldv1t )
                           
                 call stdlib${ii}$_${ri}$orglq( q, q, q, v1t, ldv1t, work(itauq1),work(iorglq), lorglq, &
                           childinfo )
              end if
              ! simultaneously diagonalize x11 and x21.
              call stdlib${ii}$_${ri}$bbcsd( jobu2, jobu1, 'N', jobv1t, 'N', m, m-p, m-q,theta, work(iphi), &
              u2, ldu2, u1, ldu1, dum2,1_${ik}$, v1t, ldv1t, work(ib11d), work(ib11e),work(ib12d), work(&
              ib12e), work(ib21d),work(ib21e), work(ib22d), work(ib22e),work(ibbcsd), lbbcsd, &
                        childinfo )
              ! permute rows and columns to place identity submatrices in
              ! preferred positions
              if( p > r ) then
                 do i = 1, r
                    iwork(i) = p - r + i
                 end do
                 do i = r + 1, p
                    iwork(i) = i - r
                 end do
                 if( wantu1 ) then
                    call stdlib${ii}$_${ri}$lapmt( .false., p, p, u1, ldu1, iwork )
                 end if
                 if( wantv1t ) then
                    call stdlib${ii}$_${ri}$lapmr( .false., p, q, v1t, ldv1t, iwork )
                 end if
              end if
           end if
           return
     end subroutine stdlib${ii}$_${ri}$orcsd2by1

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
     !! SORBDB simultaneously bidiagonalizes the blocks of an M-by-M
     !! partitioned orthogonal matrix X:
     !! [ B11 | B12 0  0 ]
     !! [ X11 | X12 ]   [ P1 |    ] [  0  |  0 -I  0 ] [ Q1 |    ]**T
     !! X = [-----------] = [---------] [----------------] [---------]   .
     !! [ X21 | X22 ]   [    | P2 ] [ B21 | B22 0  0 ] [    | Q2 ]
     !! [  0  |  0  0  I ]
     !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is
     !! not the case, then X must be transposed and/or permuted. This can be
     !! done in constant time using the TRANS and SIGNS options. See SORCSD
     !! for details.)
     !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by-
     !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are
     !! represented implicitly by Householder vectors.
     !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, 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) :: signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q
           ! Array Arguments 
           real(sp), intent(out) :: phi(*), theta(*)
           real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ====================================================================
           ! Parameters 
           
           
           
           ! Local Scalars 
           logical(lk) :: colmajor, lquery
           integer(${ik}$) :: i, lworkmin, lworkopt
           real(sp) :: z1, z2, z3, z4
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           colmajor = .not. stdlib_lsame( trans, 'T' )
           if( .not. stdlib_lsame( signs, 'O' ) ) then
              z1 = one
              z2 = one
              z3 = one
              z4 = one
           else
              z1 = one
              z2 = -one
              z3 = one
              z4 = -one
           end if
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -4_${ik}$
           else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then
              info = -5_${ik}$
           else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
              info = -7_${ik}$
           else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
              info = -9_${ik}$
           else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
              info = -9_${ik}$
           else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -11_${ik}$
           else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
              info = -11_${ik}$
           else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
              info = -13_${ik}$
           else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              lworkopt = m - q
              lworkmin = m - q
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'XORBDB', -info )
              return
           else if( lquery ) then
              return
           end if
           ! handle column-major and row-major separately
           if( colmajor ) then
              ! reduce columns 1, ..., q of x11, x12, x21, and x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_sscal( p-i+1, z1, x11(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_sscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ )
                    call stdlib${ii}$_saxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ )
                              
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_sscal( m-p-i+1, z2, x21(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_sscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ )
                    call stdlib${ii}$_saxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), &
                              1_${ik}$ )
                 end if
                 theta(i) = atan2( stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_snrm2( p-i+1, x11(&
                           i,i), 1_${ik}$ ) )
                 if( p > i ) then
                    call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
                 else if( p == i ) then
                    call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) )
                 end if
                 x11(i,i) = one
                 if ( m-p > i ) then
                    call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) )
                 else if ( m-p == i ) then
                    call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, &
                              work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_slarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,&
                               work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,&
                               work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_slarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_sscal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 )
                    call stdlib${ii}$_saxpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), &
                              ldx11 )
                 end if
                 call stdlib${ii}$_sscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 )
                 call stdlib${ii}$_saxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 &
                           )
                 if( i < q )phi(i) = atan2( stdlib${ii}$_snrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_snrm2( &
                           m-q-i+1, x12(i,i), ldx12 ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$ ) then
                       call stdlib${ii}$_slarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) )
                    else
                       call stdlib${ii}$_slarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) )
                    end if
                    x11(i,i+1) = one
                 end if
                 if ( q+i-1 < m ) then
                    if ( m-q == i ) then
                       call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                    else
                       call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                                 
                    end if
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_slarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), &
                              ldx11, work )
                    call stdlib${ii}$_slarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 if ( p > i ) then
                    call stdlib${ii}$_slarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if ( m-p > i ) then
                    call stdlib${ii}$_slarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_sscal( m-q-i+1, -z1*z4, x12(i,i), ldx12 )
                 if ( i >= m-q ) then
                    call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                 else
                    call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_slarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_slarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),&
                            x22(q+1,i), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_sscal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 )
                 if ( i == m-p-q ) then
                    call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) )
                              
                 else
                    call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)&
                               )
                 end if
                 x22(q+i,p+i) = one
                 if ( i < m-p-q ) then
                    call stdlib${ii}$_slarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), &
                              x22(q+i+1,p+i), ldx22, work )
                 end if
              end do
           else
              ! reduce columns 1, ..., q of x11, x12, x21, x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_sscal( p-i+1, z1, x11(i,i), ldx11 )
                 else
                    call stdlib${ii}$_sscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 )
                    call stdlib${ii}$_saxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),&
                               ldx11 )
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_sscal( m-p-i+1, z2, x21(i,i), ldx21 )
                 else
                    call stdlib${ii}$_sscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 )
                    call stdlib${ii}$_saxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,&
                              i), ldx21 )
                 end if
                 theta(i) = atan2( stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_snrm2( p-i+1, &
                           x11(i,i), ldx11 ) )
                 call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) )
                 x11(i,i) = one
                 if ( i == m-p ) then
                    call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) )
                 else
                    call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_slarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), &
                              ldx11, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_slarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), &
                              ldx12, work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_slarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), &
                              ldx21, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_slarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_sscal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ )
                    call stdlib${ii}$_saxpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ )
                              
                 end if
                 call stdlib${ii}$_sscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_saxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ )
                           
                 if( i < q )phi(i) = atan2( stdlib${ii}$_snrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_snrm2( m-q-&
                           i+1, x12(i,i), 1_${ik}$ ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$) then
                       call stdlib${ii}$_slarfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) )
                    else
                       call stdlib${ii}$_slarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) )
                    end if
                    x11(i+1,i) = one
                 end if
                 if ( m-q > i ) then
                    call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) )
                 else
                    call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_slarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,&
                               work )
                    call stdlib${ii}$_slarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 call stdlib${ii}$_slarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, &
                           work )
                 if ( m-p-i > 0_${ik}$ ) then
                    call stdlib${ii}$_slarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_sscal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_slarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) )
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_slarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,&
                               work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_slarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),&
                           x22(i,q+1), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_sscal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ )
                 if ( m-p-q == i ) then
                    call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) )
                              
                    x22(p+i,q+i) = one
                 else
                    call stdlib${ii}$_slarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) )
                              
                    x22(p+i,q+i) = one
                    call stdlib${ii}$_slarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+&
                              i,q+i+1), ldx22, work )
                 end if
              end do
           end if
           return
     end subroutine stdlib${ii}$_sorbdb

     module subroutine stdlib${ii}$_dorbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
     !! DORBDB simultaneously bidiagonalizes the blocks of an M-by-M
     !! partitioned orthogonal matrix X:
     !! [ B11 | B12 0  0 ]
     !! [ X11 | X12 ]   [ P1 |    ] [  0  |  0 -I  0 ] [ Q1 |    ]**T
     !! X = [-----------] = [---------] [----------------] [---------]   .
     !! [ X21 | X22 ]   [    | P2 ] [ B21 | B22 0  0 ] [    | Q2 ]
     !! [  0  |  0  0  I ]
     !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is
     !! not the case, then X must be transposed and/or permuted. This can be
     !! done in constant time using the TRANS and SIGNS options. See DORCSD
     !! for details.)
     !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by-
     !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are
     !! represented implicitly by Householder vectors.
     !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, 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) :: signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q
           ! Array Arguments 
           real(dp), intent(out) :: phi(*), theta(*)
           real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ====================================================================
           ! Parameters 
           
           
           
           ! Local Scalars 
           logical(lk) :: colmajor, lquery
           integer(${ik}$) :: i, lworkmin, lworkopt
           real(dp) :: z1, z2, z3, z4
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           colmajor = .not. stdlib_lsame( trans, 'T' )
           if( .not. stdlib_lsame( signs, 'O' ) ) then
              z1 = one
              z2 = one
              z3 = one
              z4 = one
           else
              z1 = one
              z2 = -one
              z3 = one
              z4 = -one
           end if
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -4_${ik}$
           else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then
              info = -5_${ik}$
           else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
              info = -7_${ik}$
           else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
              info = -9_${ik}$
           else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
              info = -9_${ik}$
           else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -11_${ik}$
           else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
              info = -11_${ik}$
           else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
              info = -13_${ik}$
           else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              lworkopt = m - q
              lworkmin = m - q
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'XORBDB', -info )
              return
           else if( lquery ) then
              return
           end if
           ! handle column-major and row-major separately
           if( colmajor ) then
              ! reduce columns 1, ..., q of x11, x12, x21, and x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_dscal( p-i+1, z1, x11(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_dscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ )
                    call stdlib${ii}$_daxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ )
                              
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_dscal( m-p-i+1, z2, x21(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_dscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ )
                    call stdlib${ii}$_daxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), &
                              1_${ik}$ )
                 end if
                 theta(i) = atan2( stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_dnrm2( p-i+1, x11(&
                           i,i), 1_${ik}$ ) )
                 if( p > i ) then
                    call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
                 else if( p == i ) then
                    call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) )
                 end if
                 x11(i,i) = one
                 if ( m-p > i ) then
                    call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) )
                 else if ( m-p == i ) then
                    call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, &
                              work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_dlarf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,&
                               work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,&
                               work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_dlarf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_dscal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 )
                    call stdlib${ii}$_daxpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), &
                              ldx11 )
                 end if
                 call stdlib${ii}$_dscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 )
                 call stdlib${ii}$_daxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 &
                           )
                 if( i < q )phi(i) = atan2( stdlib${ii}$_dnrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_dnrm2( &
                           m-q-i+1, x12(i,i), ldx12 ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$ ) then
                       call stdlib${ii}$_dlarfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) )
                    else
                       call stdlib${ii}$_dlarfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) )
                    end if
                    x11(i,i+1) = one
                 end if
                 if ( q+i-1 < m ) then
                    if ( m-q == i ) then
                       call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                    else
                       call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                                 
                    end if
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_dlarf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), &
                              ldx11, work )
                    call stdlib${ii}$_dlarf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 if ( p > i ) then
                    call stdlib${ii}$_dlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if ( m-p > i ) then
                    call stdlib${ii}$_dlarf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_dscal( m-q-i+1, -z1*z4, x12(i,i), ldx12 )
                 if ( i >= m-q ) then
                    call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                 else
                    call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_dlarf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_dlarf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),&
                            x22(q+1,i), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_dscal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 )
                 if ( i == m-p-q ) then
                    call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) )
                              
                 else
                    call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)&
                               )
                 end if
                 x22(q+i,p+i) = one
                 if ( i < m-p-q ) then
                    call stdlib${ii}$_dlarf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), &
                              x22(q+i+1,p+i), ldx22, work )
                 end if
              end do
           else
              ! reduce columns 1, ..., q of x11, x12, x21, x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_dscal( p-i+1, z1, x11(i,i), ldx11 )
                 else
                    call stdlib${ii}$_dscal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 )
                    call stdlib${ii}$_daxpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),&
                               ldx11 )
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_dscal( m-p-i+1, z2, x21(i,i), ldx21 )
                 else
                    call stdlib${ii}$_dscal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 )
                    call stdlib${ii}$_daxpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,&
                              i), ldx21 )
                 end if
                 theta(i) = atan2( stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_dnrm2( p-i+1, &
                           x11(i,i), ldx11 ) )
                 call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) )
                 x11(i,i) = one
                 if ( i == m-p ) then
                    call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) )
                 else
                    call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_dlarf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), &
                              ldx11, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_dlarf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), &
                              ldx12, work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_dlarf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), &
                              ldx21, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_dlarf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_dscal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ )
                    call stdlib${ii}$_daxpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ )
                              
                 end if
                 call stdlib${ii}$_dscal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_daxpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ )
                           
                 if( i < q )phi(i) = atan2( stdlib${ii}$_dnrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_dnrm2( m-q-&
                           i+1, x12(i,i), 1_${ik}$ ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$) then
                       call stdlib${ii}$_dlarfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) )
                    else
                       call stdlib${ii}$_dlarfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) )
                    end if
                    x11(i+1,i) = one
                 end if
                 if ( m-q > i ) then
                    call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) )
                 else
                    call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_dlarf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,&
                               work )
                    call stdlib${ii}$_dlarf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 call stdlib${ii}$_dlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, &
                           work )
                 if ( m-p-i > 0_${ik}$ ) then
                    call stdlib${ii}$_dlarf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_dscal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_dlarfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) )
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_dlarf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,&
                               work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_dlarf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),&
                           x22(i,q+1), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_dscal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ )
                 if ( m-p-q == i ) then
                    call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) )
                              
                 else
                    call stdlib${ii}$_dlarfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) )
                              
                    call stdlib${ii}$_dlarf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+&
                              i,q+i+1), ldx22, work )
                 end if
                 x22(p+i,q+i) = one
              end do
           end if
           return
     end subroutine stdlib${ii}$_dorbdb

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orbdb( trans, signs, m, p, q, x11, ldx11, x12, ldx12,x21, ldx21, x22, &
     !! DORBDB: simultaneously bidiagonalizes the blocks of an M-by-M
     !! partitioned orthogonal matrix X:
     !! [ B11 | B12 0  0 ]
     !! [ X11 | X12 ]   [ P1 |    ] [  0  |  0 -I  0 ] [ Q1 |    ]**T
     !! X = [-----------] = [---------] [----------------] [---------]   .
     !! [ X21 | X22 ]   [    | P2 ] [ B21 | B22 0  0 ] [    | Q2 ]
     !! [  0  |  0  0  I ]
     !! X11 is P-by-Q. Q must be no larger than P, M-P, or M-Q. (If this is
     !! not the case, then X must be transposed and/or permuted. This can be
     !! done in constant time using the TRANS and SIGNS options. See DORCSD
     !! for details.)
     !! The orthogonal matrices P1, P2, Q1, and Q2 are P-by-P, (M-P)-by-
     !! (M-P), Q-by-Q, and (M-Q)-by-(M-Q), respectively. They are
     !! represented implicitly by Householder vectors.
     !! B11, B12, B21, and B22 are Q-by-Q bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               ldx22, theta, phi, taup1,taup2, tauq1, tauq2, work, lwork, 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) :: signs, trans
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: ldx11, ldx12, ldx21, ldx22, lwork, m, p, q
           ! Array Arguments 
           real(${rk}$), intent(out) :: phi(*), theta(*)
           real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), tauq2(*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x12(ldx12,*), x21(ldx21,*), x22(ldx22,*)
                     
        ! ====================================================================
           ! Parameters 
           
           
           
           ! Local Scalars 
           logical(lk) :: colmajor, lquery
           integer(${ik}$) :: i, lworkmin, lworkopt
           real(${rk}$) :: z1, z2, z3, z4
           ! Intrinsic Functions
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           colmajor = .not. stdlib_lsame( trans, 'T' )
           if( .not. stdlib_lsame( signs, 'O' ) ) then
              z1 = one
              z2 = one
              z3 = one
              z4 = one
           else
              z1 = one
              z2 = -one
              z3 = one
              z4 = -one
           end if
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( p < 0_${ik}$ .or. p > m ) then
              info = -4_${ik}$
           else if( q < 0_${ik}$ .or. q > p .or. q > m-p .or.q > m-q ) then
              info = -5_${ik}$
           else if( colmajor .and. ldx11 < max( 1_${ik}$, p ) ) then
              info = -7_${ik}$
           else if( .not.colmajor .and. ldx11 < max( 1_${ik}$, q ) ) then
              info = -7_${ik}$
           else if( colmajor .and. ldx12 < max( 1_${ik}$, p ) ) then
              info = -9_${ik}$
           else if( .not.colmajor .and. ldx12 < max( 1_${ik}$, m-q ) ) then
              info = -9_${ik}$
           else if( colmajor .and. ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -11_${ik}$
           else if( .not.colmajor .and. ldx21 < max( 1_${ik}$, q ) ) then
              info = -11_${ik}$
           else if( colmajor .and. ldx22 < max( 1_${ik}$, m-p ) ) then
              info = -13_${ik}$
           else if( .not.colmajor .and. ldx22 < max( 1_${ik}$, m-q ) ) then
              info = -13_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              lworkopt = m - q
              lworkmin = m - q
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not. lquery ) then
                 info = -21_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'XORBDB', -info )
              return
           else if( lquery ) then
              return
           end if
           ! handle column-major and row-major separately
           if( colmajor ) then
              ! reduce columns 1, ..., q of x11, x12, x21, and x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_${ri}$scal( p-i+1, z1, x11(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_${ri}$scal( p-i+1, z1*cos(phi(i-1)), x11(i,i), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$axpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i,i-1),1_${ik}$, x11(i,i), 1_${ik}$ )
                              
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_${ri}$scal( m-p-i+1, z2, x21(i,i), 1_${ik}$ )
                 else
                    call stdlib${ii}$_${ri}$scal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$axpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i,i-1),1_${ik}$, x21(i,i), &
                              1_${ik}$ )
                 end if
                 theta(i) = atan2( stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( p-i+1, x11(&
                           i,i), 1_${ik}$ ) )
                 if( p > i ) then
                    call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
                 else if( p == i ) then
                    call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i,i), 1_${ik}$, taup1(i) )
                 end if
                 x11(i,i) = one
                 if ( m-p > i ) then
                    call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$,taup2(i) )
                 else if ( m-p == i ) then
                    call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i), 1_${ik}$, taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i),x11(i,i+1), ldx11, &
                              work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_${ri}$larf( 'L', p-i+1, m-q-i+1, x11(i,i), 1_${ik}$, taup1(i),x12(i,i), ldx12,&
                               work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21,&
                               work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, m-q-i+1, x21(i,i), 1_${ik}$, taup2(i),x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_${ri}$scal( q-i, -z1*z3*sin(theta(i)), x11(i,i+1),ldx11 )
                    call stdlib${ii}$_${ri}$axpy( q-i, z2*z3*cos(theta(i)), x21(i,i+1), ldx21,x11(i,i+1), &
                              ldx11 )
                 end if
                 call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), ldx12 )
                 call stdlib${ii}$_${ri}$axpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), ldx22,x12(i,i), ldx12 &
                           )
                 if( i < q )phi(i) = atan2( stdlib${ii}$_${ri}$nrm2( q-i, x11(i,i+1), ldx11 ),stdlib${ii}$_${ri}$nrm2( &
                           m-q-i+1, x12(i,i), ldx12 ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$ ) then
                       call stdlib${ii}$_${ri}$larfgp( q-i, x11(i,i+1), x11(i,i+1), ldx11,tauq1(i) )
                    else
                       call stdlib${ii}$_${ri}$larfgp( q-i, x11(i,i+1), x11(i,i+2), ldx11,tauq1(i) )
                    end if
                    x11(i,i+1) = one
                 end if
                 if ( q+i-1 < m ) then
                    if ( m-q == i ) then
                       call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                    else
                       call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                                 
                    end if
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x11(i+1,i+1), &
                              ldx11, work )
                    call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i, x11(i,i+1), ldx11, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 if ( p > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if ( m-p > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', m-p-i, m-q-i+1, x12(i,i), ldx12,tauq2(i), x22(i+1,i), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4, x12(i,i), ldx12 )
                 if ( i >= m-q ) then
                    call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), ldx12,tauq2(i) )
                 else
                    call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i+1), ldx12,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', p-i, m-q-i+1, x12(i,i), ldx12, tauq2(i),x12(i+1,i), &
                              ldx12, work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ri}$larf( 'R', m-p-q, m-q-i+1, x12(i,i), ldx12,tauq2(i),&
                            x22(q+1,i), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_${ri}$scal( m-p-q-i+1, z2*z4, x22(q+i,p+i), ldx22 )
                 if ( i == m-p-q ) then
                    call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i),ldx22, tauq2(p+i) )
                              
                 else
                    call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(q+i,p+i), x22(q+i,p+i+1),ldx22, tauq2(p+i)&
                               )
                 end if
                 x22(q+i,p+i) = one
                 if ( i < m-p-q ) then
                    call stdlib${ii}$_${ri}$larf( 'R', m-p-q-i, m-p-q-i+1, x22(q+i,p+i), ldx22,tauq2(p+i), &
                              x22(q+i+1,p+i), ldx22, work )
                 end if
              end do
           else
              ! reduce columns 1, ..., q of x11, x12, x21, x22
              do i = 1, q
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_${ri}$scal( p-i+1, z1, x11(i,i), ldx11 )
                 else
                    call stdlib${ii}$_${ri}$scal( p-i+1, z1*cos(phi(i-1)), x11(i,i), ldx11 )
                    call stdlib${ii}$_${ri}$axpy( p-i+1, -z1*z3*z4*sin(phi(i-1)), x12(i-1,i),ldx12, x11(i,i),&
                               ldx11 )
                 end if
                 if( i == 1_${ik}$ ) then
                    call stdlib${ii}$_${ri}$scal( m-p-i+1, z2, x21(i,i), ldx21 )
                 else
                    call stdlib${ii}$_${ri}$scal( m-p-i+1, z2*cos(phi(i-1)), x21(i,i), ldx21 )
                    call stdlib${ii}$_${ri}$axpy( m-p-i+1, -z2*z3*z4*sin(phi(i-1)), x22(i-1,i),ldx22, x21(i,&
                              i), ldx21 )
                 end if
                 theta(i) = atan2( stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), ldx21 ),stdlib${ii}$_${ri}$nrm2( p-i+1, &
                           x11(i,i), ldx11 ) )
                 call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i,i+1), ldx11, taup1(i) )
                 x11(i,i) = one
                 if ( i == m-p ) then
                    call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i), ldx21,taup2(i) )
                 else
                    call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i,i+1), ldx21,taup2(i) )
                 end if
                 x21(i,i) = one
                 if ( q > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', q-i, p-i+1, x11(i,i), ldx11, taup1(i),x11(i+1,i), &
                              ldx11, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', m-q-i+1, p-i+1, x11(i,i), ldx11,taup1(i), x12(i,i), &
                              ldx12, work )
                 end if
                 if ( q > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', q-i, m-p-i+1, x21(i,i), ldx21, taup2(i),x21(i+1,i), &
                              ldx21, work )
                 end if
                 if ( m-q+1 > i ) then
                    call stdlib${ii}$_${ri}$larf( 'R', m-q-i+1, m-p-i+1, x21(i,i), ldx21,taup2(i), x22(i,i), &
                              ldx22, work )
                 end if
                 if( i < q ) then
                    call stdlib${ii}$_${ri}$scal( q-i, -z1*z3*sin(theta(i)), x11(i+1,i), 1_${ik}$ )
                    call stdlib${ii}$_${ri}$axpy( q-i, z2*z3*cos(theta(i)), x21(i+1,i), 1_${ik}$,x11(i+1,i), 1_${ik}$ )
                              
                 end if
                 call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4*sin(theta(i)), x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$axpy( m-q-i+1, z2*z4*cos(theta(i)), x22(i,i), 1_${ik}$,x12(i,i), 1_${ik}$ )
                           
                 if( i < q )phi(i) = atan2( stdlib${ii}$_${ri}$nrm2( q-i, x11(i+1,i), 1_${ik}$ ),stdlib${ii}$_${ri}$nrm2( m-q-&
                           i+1, x12(i,i), 1_${ik}$ ) )
                 if( i < q ) then
                    if ( q-i == 1_${ik}$) then
                       call stdlib${ii}$_${ri}$larfgp( q-i, x11(i+1,i), x11(i+1,i), 1_${ik}$,tauq1(i) )
                    else
                       call stdlib${ii}$_${ri}$larfgp( q-i, x11(i+1,i), x11(i+2,i), 1_${ik}$,tauq1(i) )
                    end if
                    x11(i+1,i) = one
                 end if
                 if ( m-q > i ) then
                    call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$,tauq2(i) )
                 else
                    call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i,i), 1_${ik}$,tauq2(i) )
                 end if
                 x12(i,i) = one
                 if( i < q ) then
                    call stdlib${ii}$_${ri}$larf( 'L', q-i, p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x11(i+1,i+1), ldx11,&
                               work )
                    call stdlib${ii}$_${ri}$larf( 'L', q-i, m-p-i, x11(i+1,i), 1_${ik}$, tauq1(i),x21(i+1,i+1), &
                              ldx21, work )
                 end if
                 call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12, &
                           work )
                 if ( m-p-i > 0_${ik}$ ) then
                    call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, m-p-i, x12(i,i), 1_${ik}$, tauq2(i),x22(i,i+1), &
                              ldx22, work )
                 end if
              end do
              ! reduce columns q + 1, ..., p of x12, x22
              do i = q + 1, p
                 call stdlib${ii}$_${ri}$scal( m-q-i+1, -z1*z4, x12(i,i), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$larfgp( m-q-i+1, x12(i,i), x12(i+1,i), 1_${ik}$, tauq2(i) )
                 x12(i,i) = one
                 if ( p > i ) then
                    call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, p-i, x12(i,i), 1_${ik}$, tauq2(i),x12(i,i+1), ldx12,&
                               work )
                 end if
                 if( m-p-q >= 1_${ik}$ )call stdlib${ii}$_${ri}$larf( 'L', m-q-i+1, m-p-q, x12(i,i), 1_${ik}$, tauq2(i),&
                           x22(i,q+1), ldx22, work )
              end do
              ! reduce columns p + 1, ..., m - q of x12, x22
              do i = 1, m - p - q
                 call stdlib${ii}$_${ri}$scal( m-p-q-i+1, z2*z4, x22(p+i,q+i), 1_${ik}$ )
                 if ( m-p-q == i ) then
                    call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i,q+i), 1_${ik}$,tauq2(p+i) )
                              
                 else
                    call stdlib${ii}$_${ri}$larfgp( m-p-q-i+1, x22(p+i,q+i), x22(p+i+1,q+i), 1_${ik}$,tauq2(p+i) )
                              
                    call stdlib${ii}$_${ri}$larf( 'L', m-p-q-i+1, m-p-q-i, x22(p+i,q+i), 1_${ik}$,tauq2(p+i), x22(p+&
                              i,q+i+1), ldx22, work )
                 end if
                 x22(p+i,q+i) = one
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ri}$orbdb

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! SORBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P,
     !! M-P, or M-Q. Routines SORBDB2, SORBDB3, and SORBDB4 handle cases in
     !! which Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(sp), intent(out) :: phi(*), theta(*)
           real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(sp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < q .or. m-p < q ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. m-q < q ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-2
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB1', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., q of x11 and x21
           do i = 1, q
              call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              theta(i) = atan2( x21(i,i), x11(i,i) )
              c = cos( theta(i) )
              s = sin( theta(i) )
              x11(i,i) = one
              x21(i,i) = one
              call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
              call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
              if( i < q ) then
                 call stdlib${ii}$_srot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s )
                 call stdlib${ii}$_slarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) )
                 s = x21(i,i+1)
                 x21(i,i+1) = one
                 call stdlib${ii}$_slarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), &
                           ldx11, work(ilarf) )
                 call stdlib${ii}$_slarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), &
                           ldx21, work(ilarf) )
                 c = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,&
                           i+1), 1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
                 call stdlib${ii}$_sorbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,&
                           i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo )
              end if
           end do
           return
     end subroutine stdlib${ii}$_sorbdb1

     module subroutine stdlib${ii}$_dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB1 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P,
     !! M-P, or M-Q. Routines DORBDB2, DORBDB3, and DORBDB4 handle cases in
     !! which Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(dp), intent(out) :: phi(*), theta(*)
           real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(dp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < q .or. m-p < q ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. m-q < q ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-2
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB1', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., q of x11 and x21
           do i = 1, q
              call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              theta(i) = atan2( x21(i,i), x11(i,i) )
              c = cos( theta(i) )
              s = sin( theta(i) )
              x11(i,i) = one
              x21(i,i) = one
              call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
              call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
              if( i < q ) then
                 call stdlib${ii}$_drot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s )
                 call stdlib${ii}$_dlarfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) )
                 s = x21(i,i+1)
                 x21(i,i+1) = one
                 call stdlib${ii}$_dlarf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), &
                           ldx11, work(ilarf) )
                 call stdlib${ii}$_dlarf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), &
                           ldx21, work(ilarf) )
                 c = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,&
                           i+1), 1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
                 call stdlib${ii}$_dorbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,&
                           i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo )
              end if
           end do
           return
     end subroutine stdlib${ii}$_dorbdb1

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orbdb1( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB1: simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. Q must be no larger than P,
     !! M-P, or M-Q. Routines DORBDB2, DORBDB3, and DORBDB4 handle cases in
     !! which Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are Q-by-Q bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(${rk}$), intent(out) :: phi(*), theta(*)
           real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(${rk}$) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < q .or. m-p < q ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. m-q < q ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-2
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB1', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., q of x11 and x21
           do i = 1, q
              call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              theta(i) = atan2( x21(i,i), x11(i,i) )
              c = cos( theta(i) )
              s = sin( theta(i) )
              x11(i,i) = one
              x21(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
              call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
              if( i < q ) then
                 call stdlib${ii}$_${ri}$rot( q-i, x11(i,i+1), ldx11, x21(i,i+1), ldx21, c, s )
                 call stdlib${ii}$_${ri}$larfgp( q-i, x21(i,i+1), x21(i,i+2), ldx21, tauq1(i) )
                 s = x21(i,i+1)
                 x21(i,i+1) = one
                 call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x11(i+1,i+1), &
                           ldx11, work(ilarf) )
                 call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i, x21(i,i+1), ldx21, tauq1(i),x21(i+1,i+1), &
                           ldx21, work(ilarf) )
                 c = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i+1), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,&
                           i+1), 1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
                 call stdlib${ii}$_${ri}$orbdb5( p-i, m-p-i, q-i-1, x11(i+1,i+1), 1_${ik}$,x21(i+1,i+1), 1_${ik}$, x11(i+1,&
                           i+2), ldx11,x21(i+1,i+2), ldx21, work(iorbdb5), lorbdb5,childinfo )
              end if
           end do
           return
     end subroutine stdlib${ii}$_${ri}$orbdb1

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! SORBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P,
     !! Q, or M-Q. Routines SORBDB1, SORBDB3, and SORBDB4 handle cases in
     !! which P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(sp), intent(out) :: phi(*), theta(*)
           real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(sp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < 0_${ik}$ .or. p > m-p ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB2', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., p of x11 and x21
           do i = 1, p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_srot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s )
              end if
              call stdlib${ii}$_slarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              c = x11(i,i)
              x11(i,i) = one
              call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_slarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, &
                        work(ilarf) )
              s = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i+1, x21(i,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_sorbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), &
                        ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_sscal( p-i, negone, x11(i+1,i), 1_${ik}$ )
              call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              if( i < p ) then
                 call stdlib${ii}$_slarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) )
                 phi(i) = atan2( x11(i+1,i), x21(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x11(i+1,i) = one
                 call stdlib${ii}$_slarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, &
                           work(ilarf) )
              end if
              x21(i,i) = one
              call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to the identity matrix
           do i = p + 1, q
              call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              x21(i,i) = one
              call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_sorbdb2

     module subroutine stdlib${ii}$_dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB2 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P,
     !! Q, or M-Q. Routines DORBDB1, DORBDB3, and DORBDB4 handle cases in
     !! which P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(dp), intent(out) :: phi(*), theta(*)
           real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(dp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < 0_${ik}$ .or. p > m-p ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB2', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., p of x11 and x21
           do i = 1, p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_drot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s )
              end if
              call stdlib${ii}$_dlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              c = x11(i,i)
              x11(i,i) = one
              call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_dlarf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, &
                        work(ilarf) )
              s = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i+1, x21(i,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_dorbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), &
                        ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_dscal( p-i, negone, x11(i+1,i), 1_${ik}$ )
              call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              if( i < p ) then
                 call stdlib${ii}$_dlarfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) )
                 phi(i) = atan2( x11(i+1,i), x21(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x11(i+1,i) = one
                 call stdlib${ii}$_dlarf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, &
                           work(ilarf) )
              end if
              x21(i,i) = one
              call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to the identity matrix
           do i = p + 1, q
              call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              x21(i,i) = one
              call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_dorbdb2

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orbdb2( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB2: simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. P must be no larger than M-P,
     !! Q, or M-Q. Routines DORBDB1, DORBDB3, and DORBDB4 handle cases in
     !! which P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are P-by-P bidiagonal matrices represented implicitly by
     !! angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(${rk}$), intent(out) :: phi(*), theta(*)
           real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(${rk}$) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < 0_${ik}$ .or. p > m-p ) then
              info = -2_${ik}$
           else if( q < 0_${ik}$ .or. q < p .or. m-q < p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p-1, m-p, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB2', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., p of x11 and x21
           do i = 1, p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$rot( q-i+1, x11(i,i), ldx11, x21(i-1,i), ldx21, c, s )
              end if
              call stdlib${ii}$_${ri}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              c = x11(i,i)
              x11(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_${ri}$larf( 'R', m-p-i+1, q-i+1, x11(i,i), ldx11, tauq1(i),x21(i,i), ldx21, &
                        work(ilarf) )
              s = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i+1, x21(i,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_${ri}$orbdb5( p-i, m-p-i+1, q-i, x11(i+1,i), 1_${ik}$, x21(i,i), 1_${ik}$,x11(i+1,i+1), &
                        ldx11, x21(i,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_${ri}$scal( p-i, negone, x11(i+1,i), 1_${ik}$ )
              call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              if( i < p ) then
                 call stdlib${ii}$_${ri}$larfgp( p-i, x11(i+1,i), x11(i+2,i), 1_${ik}$, taup1(i) )
                 phi(i) = atan2( x11(i+1,i), x21(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x11(i+1,i) = one
                 call stdlib${ii}$_${ri}$larf( 'L', p-i, q-i, x11(i+1,i), 1_${ik}$, taup1(i),x11(i+1,i+1), ldx11, &
                           work(ilarf) )
              end if
              x21(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to the identity matrix
           do i = p + 1, q
              call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i), x21(i+1,i), 1_${ik}$, taup2(i) )
              x21(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i, x21(i,i), 1_${ik}$, taup2(i),x21(i,i+1), ldx21, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_${ri}$orbdb2

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! SORBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P,
     !! Q, or M-Q. Routines SORBDB1, SORBDB2, and SORBDB4 handle cases in
     !! which M-P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(sp), intent(out) :: phi(*), theta(*)
           real(sp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(sp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( 2_${ik}$*p < m .or. p > m ) then
              info = -2_${ik}$
           else if( q < m-p .or. m-q < m-p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB3', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., m-p of x11 and x21
           do i = 1, m-p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_srot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s )
              end if
              call stdlib${ii}$_slarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              s = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_slarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_slarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              c = sqrt( stdlib${ii}$_snrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_sorbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), &
                        ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              if( i < m-p ) then
                 call stdlib${ii}$_slarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) )
                 phi(i) = atan2( x21(i+1,i), x11(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x21(i+1,i) = one
                 call stdlib${ii}$_slarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, &
                           work(ilarf) )
              end if
              x11(i,i) = one
              call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x11 to the identity matrix
           do i = m-p + 1, q
              call stdlib${ii}$_slarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              x11(i,i) = one
              call stdlib${ii}$_slarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_sorbdb3

     module subroutine stdlib${ii}$_dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB3 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P,
     !! Q, or M-Q. Routines DORBDB1, DORBDB2, and DORBDB4 handle cases in
     !! which M-P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(dp), intent(out) :: phi(*), theta(*)
           real(dp), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(dp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( 2_${ik}$*p < m .or. p > m ) then
              info = -2_${ik}$
           else if( q < m-p .or. m-q < m-p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB3', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., m-p of x11 and x21
           do i = 1, m-p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_drot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s )
              end if
              call stdlib${ii}$_dlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              s = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_dlarf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_dlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              c = sqrt( stdlib${ii}$_dnrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_dorbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), &
                        ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              if( i < m-p ) then
                 call stdlib${ii}$_dlarfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) )
                 phi(i) = atan2( x21(i+1,i), x11(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x21(i+1,i) = one
                 call stdlib${ii}$_dlarf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, &
                           work(ilarf) )
              end if
              x11(i,i) = one
              call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x11 to the identity matrix
           do i = m-p + 1, q
              call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              x11(i,i) = one
              call stdlib${ii}$_dlarf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_dorbdb3

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orbdb3( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB3: simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-P must be no larger than P,
     !! Q, or M-Q. Routines DORBDB1, DORBDB2, and DORBDB4 handle cases in
     !! which M-P is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-P)-by-(M-P) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               work, lwork, 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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(${rk}$), intent(out) :: phi(*), theta(*)
           real(${rk}$), intent(out) :: taup1(*), taup2(*), tauq1(*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(${rk}$) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( 2_${ik}$*p < m .or. p > m ) then
              info = -2_${ik}$
           else if( q < m-p .or. m-q < m-p ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( p, m-p-1, q-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q-1
              lworkopt = max( ilarf+llarf-1, iorbdb5+lorbdb5-1 )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB3', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce rows 1, ..., m-p of x11 and x21
           do i = 1, m-p
              if( i > 1_${ik}$ ) then
                 call stdlib${ii}$_${ri}$rot( q-i+1, x11(i-1,i), ldx11, x21(i,i), ldx11, c, s )
              end if
              call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              s = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'R', p-i+1, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              c = sqrt( stdlib${ii}$_${ri}$nrm2( p-i+1, x11(i,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,i), 1_${ik}$ &
                        )**2_${ik}$ )
              theta(i) = atan2( s, c )
              call stdlib${ii}$_${ri}$orbdb5( p-i+1, m-p-i, q-i, x11(i,i), 1_${ik}$, x21(i+1,i), 1_${ik}$,x11(i,i+1), &
                        ldx11, x21(i+1,i+1), ldx21,work(iorbdb5), lorbdb5, childinfo )
              call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              if( i < m-p ) then
                 call stdlib${ii}$_${ri}$larfgp( m-p-i, x21(i+1,i), x21(i+2,i), 1_${ik}$, taup2(i) )
                 phi(i) = atan2( x21(i+1,i), x11(i,i) )
                 c = cos( phi(i) )
                 s = sin( phi(i) )
                 x21(i+1,i) = one
                 call stdlib${ii}$_${ri}$larf( 'L', m-p-i, q-i, x21(i+1,i), 1_${ik}$, taup2(i),x21(i+1,i+1), ldx21, &
                           work(ilarf) )
              end if
              x11(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           ! reduce the bottom-right portion of x11 to the identity matrix
           do i = m-p + 1, q
              call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i), x11(i+1,i), 1_${ik}$, taup1(i) )
              x11(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i, x11(i,i), 1_${ik}$, taup1(i), x11(i,i+1),ldx11, work(&
                        ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_${ri}$orbdb3

#:endif
#:endfor



     module subroutine stdlib${ii}$_sorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! SORBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P,
     !! M-P, or Q. Routines SORBDB1, SORBDB2, and SORBDB3 handle cases in
     !! which M-Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               phantom, work, lwork,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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(sp), intent(out) :: phi(*), theta(*)
           real(sp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*)
           real(sp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(sp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < m-q .or. m-p < m-q ) then
              info = -2_${ik}$
           else if( q < m-q .or. q > m ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( q-1, p-1, m-p-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q
              lworkopt = ilarf + llarf - 1_${ik}$
              lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB4', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., m-q of x11 and x21
           do i = 1, m-q
              if( i == 1_${ik}$ ) then
                 do j = 1, m
                    phantom(j) = zero
                 end do
                 call stdlib${ii}$_sorbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, &
                           ldx21, work(iorbdb5),lorbdb5, childinfo )
                 call stdlib${ii}$_sscal( p, negone, phantom(1_${ik}$), 1_${ik}$ )
                 call stdlib${ii}$_slarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) )
                 call stdlib${ii}$_slarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) )
                 theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 phantom(1_${ik}$) = one
                 phantom(p+1) = one
                 call stdlib${ii}$_slarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) )
                           
                 call stdlib${ii}$_slarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)&
                            )
              else
                 call stdlib${ii}$_sorbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)&
                           , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo )
                 call stdlib${ii}$_sscal( p-i+1, negone, x11(i,i-1), 1_${ik}$ )
                 call stdlib${ii}$_slarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) )
                 call stdlib${ii}$_slarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) )
                 theta(i) = atan2( x11(i,i-1), x21(i,i-1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 x11(i,i-1) = one
                 x21(i,i-1) = one
                 call stdlib${ii}$_slarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, &
                           work(ilarf) )
                 call stdlib${ii}$_slarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, &
                           work(ilarf) )
              end if
              call stdlib${ii}$_srot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c )
              call stdlib${ii}$_slarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              c = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_slarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              if( i < m-q ) then
                 s = sqrt( stdlib${ii}$_snrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_snrm2( m-p-i, x21(i+1,i),&
                            1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
              end if
           end do
           ! reduce the bottom-right portion of x11 to [ i 0 ]
           do i = m - q + 1, p
              call stdlib${ii}$_slarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              x11(i,i) = one
              call stdlib${ii}$_slarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_slarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, &
                        work(ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to [ 0 i ]
           do i = p + 1, q
              call stdlib${ii}$_slarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) )
                        
              x21(m-q+i-p,i) = one
              call stdlib${ii}$_slarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)&
                        , ldx21, work(ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_sorbdb4

     module subroutine stdlib${ii}$_dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB4 simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P,
     !! M-P, or Q. Routines DORBDB1, DORBDB2, and DORBDB3 handle cases in
     !! which M-Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               phantom, work, lwork,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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(dp), intent(out) :: phi(*), theta(*)
           real(dp), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*)
           real(dp), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(dp) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < m-q .or. m-p < m-q ) then
              info = -2_${ik}$
           else if( q < m-q .or. q > m ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( q-1, p-1, m-p-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q
              lworkopt = ilarf + llarf - 1_${ik}$
              lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB4', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., m-q of x11 and x21
           do i = 1, m-q
              if( i == 1_${ik}$ ) then
                 do j = 1, m
                    phantom(j) = zero
                 end do
                 call stdlib${ii}$_dorbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, &
                           ldx21, work(iorbdb5),lorbdb5, childinfo )
                 call stdlib${ii}$_dscal( p, negone, phantom(1_${ik}$), 1_${ik}$ )
                 call stdlib${ii}$_dlarfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) )
                 call stdlib${ii}$_dlarfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) )
                 theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 phantom(1_${ik}$) = one
                 phantom(p+1) = one
                 call stdlib${ii}$_dlarf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) )
                           
                 call stdlib${ii}$_dlarf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)&
                            )
              else
                 call stdlib${ii}$_dorbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)&
                           , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo )
                 call stdlib${ii}$_dscal( p-i+1, negone, x11(i,i-1), 1_${ik}$ )
                 call stdlib${ii}$_dlarfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) )
                 call stdlib${ii}$_dlarfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) )
                 theta(i) = atan2( x11(i,i-1), x21(i,i-1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 x11(i,i-1) = one
                 x21(i,i-1) = one
                 call stdlib${ii}$_dlarf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, &
                           work(ilarf) )
                 call stdlib${ii}$_dlarf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, &
                           work(ilarf) )
              end if
              call stdlib${ii}$_drot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c )
              call stdlib${ii}$_dlarfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              c = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_dlarf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              if( i < m-q ) then
                 s = sqrt( stdlib${ii}$_dnrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_dnrm2( m-p-i, x21(i+1,i),&
                            1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
              end if
           end do
           ! reduce the bottom-right portion of x11 to [ i 0 ]
           do i = m - q + 1, p
              call stdlib${ii}$_dlarfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              x11(i,i) = one
              call stdlib${ii}$_dlarf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_dlarf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, &
                        work(ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to [ 0 i ]
           do i = p + 1, q
              call stdlib${ii}$_dlarfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) )
                        
              x21(m-q+i-p,i) = one
              call stdlib${ii}$_dlarf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)&
                        , ldx21, work(ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_dorbdb4

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     module subroutine stdlib${ii}$_${ri}$orbdb4( m, p, q, x11, ldx11, x21, ldx21, theta, phi,taup1, taup2, tauq1, &
     !! DORBDB4: simultaneously bidiagonalizes the blocks of a tall and skinny
     !! matrix X with orthonomal columns:
     !! [ B11 ]
     !! [ X11 ]   [ P1 |    ] [  0  ]
     !! [-----] = [---------] [-----] Q1**T .
     !! [ X21 ]   [    | P2 ] [ B21 ]
     !! [  0  ]
     !! X11 is P-by-Q, and X21 is (M-P)-by-Q. M-Q must be no larger than P,
     !! M-P, or Q. Routines DORBDB1, DORBDB2, and DORBDB3 handle cases in
     !! which M-Q is not the minimum dimension.
     !! The orthogonal matrices P1, P2, and Q1 are P-by-P, (M-P)-by-(M-P),
     !! and (M-Q)-by-(M-Q), respectively. They are represented implicitly by
     !! Householder vectors.
     !! B11 and B12 are (M-Q)-by-(M-Q) bidiagonal matrices represented
     !! implicitly by angles THETA, PHI.
               phantom, work, lwork,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 
           integer(${ik}$), intent(out) :: info
           integer(${ik}$), intent(in) :: lwork, m, p, q, ldx11, ldx21
           ! Array Arguments 
           real(${rk}$), intent(out) :: phi(*), theta(*)
           real(${rk}$), intent(out) :: phantom(*), taup1(*), taup2(*), tauq1(*), work(*)
           real(${rk}$), intent(inout) :: x11(ldx11,*), x21(ldx21,*)
        ! ====================================================================
           
           ! Local Scalars 
           real(${rk}$) :: c, s
           integer(${ik}$) :: childinfo, i, ilarf, iorbdb5, j, llarf, lorbdb5, lworkmin, &
                     lworkopt
           logical(lk) :: lquery
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           lquery = lwork == -1_${ik}$
           if( m < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( p < m-q .or. m-p < m-q ) then
              info = -2_${ik}$
           else if( q < m-q .or. q > m ) then
              info = -3_${ik}$
           else if( ldx11 < max( 1_${ik}$, p ) ) then
              info = -5_${ik}$
           else if( ldx21 < max( 1_${ik}$, m-p ) ) then
              info = -7_${ik}$
           end if
           ! compute workspace
           if( info == 0_${ik}$ ) then
              ilarf = 2_${ik}$
              llarf = max( q-1, p-1, m-p-1 )
              iorbdb5 = 2_${ik}$
              lorbdb5 = q
              lworkopt = ilarf + llarf - 1_${ik}$
              lworkopt = max( lworkopt, iorbdb5 + lorbdb5 - 1_${ik}$ )
              lworkmin = lworkopt
              work(1_${ik}$) = lworkopt
              if( lwork < lworkmin .and. .not.lquery ) then
                info = -14_${ik}$
              end if
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB4', -info )
              return
           else if( lquery ) then
              return
           end if
           ! reduce columns 1, ..., m-q of x11 and x21
           do i = 1, m-q
              if( i == 1_${ik}$ ) then
                 do j = 1, m
                    phantom(j) = zero
                 end do
                 call stdlib${ii}$_${ri}$orbdb5( p, m-p, q, phantom(1_${ik}$), 1_${ik}$, phantom(p+1), 1_${ik}$,x11, ldx11, x21, &
                           ldx21, work(iorbdb5),lorbdb5, childinfo )
                 call stdlib${ii}$_${ri}$scal( p, negone, phantom(1_${ik}$), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$larfgp( p, phantom(1_${ik}$), phantom(2_${ik}$), 1_${ik}$, taup1(1_${ik}$) )
                 call stdlib${ii}$_${ri}$larfgp( m-p, phantom(p+1), phantom(p+2), 1_${ik}$, taup2(1_${ik}$) )
                 theta(i) = atan2( phantom(1_${ik}$), phantom(p+1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 phantom(1_${ik}$) = one
                 phantom(p+1) = one
                 call stdlib${ii}$_${ri}$larf( 'L', p, q, phantom(1_${ik}$), 1_${ik}$, taup1(1_${ik}$), x11, ldx11,work(ilarf) )
                           
                 call stdlib${ii}$_${ri}$larf( 'L', m-p, q, phantom(p+1), 1_${ik}$, taup2(1_${ik}$), x21,ldx21, work(ilarf)&
                            )
              else
                 call stdlib${ii}$_${ri}$orbdb5( p-i+1, m-p-i+1, q-i+1, x11(i,i-1), 1_${ik}$,x21(i,i-1), 1_${ik}$, x11(i,i)&
                           , ldx11, x21(i,i),ldx21, work(iorbdb5), lorbdb5, childinfo )
                 call stdlib${ii}$_${ri}$scal( p-i+1, negone, x11(i,i-1), 1_${ik}$ )
                 call stdlib${ii}$_${ri}$larfgp( p-i+1, x11(i,i-1), x11(i+1,i-1), 1_${ik}$, taup1(i) )
                 call stdlib${ii}$_${ri}$larfgp( m-p-i+1, x21(i,i-1), x21(i+1,i-1), 1_${ik}$,taup2(i) )
                 theta(i) = atan2( x11(i,i-1), x21(i,i-1) )
                 c = cos( theta(i) )
                 s = sin( theta(i) )
                 x11(i,i-1) = one
                 x21(i,i-1) = one
                 call stdlib${ii}$_${ri}$larf( 'L', p-i+1, q-i+1, x11(i,i-1), 1_${ik}$, taup1(i),x11(i,i), ldx11, &
                           work(ilarf) )
                 call stdlib${ii}$_${ri}$larf( 'L', m-p-i+1, q-i+1, x21(i,i-1), 1_${ik}$, taup2(i),x21(i,i), ldx21, &
                           work(ilarf) )
              end if
              call stdlib${ii}$_${ri}$rot( q-i+1, x11(i,i), ldx11, x21(i,i), ldx21, s, -c )
              call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(i,i), x21(i,i+1), ldx21, tauq1(i) )
              c = x21(i,i)
              x21(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_${ri}$larf( 'R', m-p-i, q-i+1, x21(i,i), ldx21, tauq1(i),x21(i+1,i), ldx21, &
                        work(ilarf) )
              if( i < m-q ) then
                 s = sqrt( stdlib${ii}$_${ri}$nrm2( p-i, x11(i+1,i), 1_${ik}$ )**2_${ik}$+ stdlib${ii}$_${ri}$nrm2( m-p-i, x21(i+1,i),&
                            1_${ik}$ )**2_${ik}$ )
                 phi(i) = atan2( s, c )
              end if
           end do
           ! reduce the bottom-right portion of x11 to [ i 0 ]
           do i = m - q + 1, p
              call stdlib${ii}$_${ri}$larfgp( q-i+1, x11(i,i), x11(i,i+1), ldx11, tauq1(i) )
              x11(i,i) = one
              call stdlib${ii}$_${ri}$larf( 'R', p-i, q-i+1, x11(i,i), ldx11, tauq1(i),x11(i+1,i), ldx11, &
                        work(ilarf) )
              call stdlib${ii}$_${ri}$larf( 'R', q-p, q-i+1, x11(i,i), ldx11, tauq1(i),x21(m-q+1,i), ldx21, &
                        work(ilarf) )
           end do
           ! reduce the bottom-right portion of x21 to [ 0 i ]
           do i = p + 1, q
              call stdlib${ii}$_${ri}$larfgp( q-i+1, x21(m-q+i-p,i), x21(m-q+i-p,i+1), ldx21,tauq1(i) )
                        
              x21(m-q+i-p,i) = one
              call stdlib${ii}$_${ri}$larf( 'R', q-i, q-i+1, x21(m-q+i-p,i), ldx21, tauq1(i),x21(m-q+i-p+1,i)&
                        , ldx21, work(ilarf) )
           end do
           return
     end subroutine stdlib${ii}$_${ri}$orbdb4

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! SORBDB5 orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then some other vector from the orthogonal complement
     !! is returned. This vector is chosen in an arbitrary but deterministic
     !! way.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(sp), intent(out) :: work(*)
           real(sp), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, j
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB5', -info )
              return
           end if
           ! project x onto the orthogonal complement of q
           call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, &
                     childinfo )
           ! if the projection is nonzero, then return
           if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) &
                     then
              return
           end if
           ! project each standard basis vector e_1,...,e_m1 in turn, stopping
           ! when a nonzero projection is found
           do i = 1, m1
              do j = 1, m1
                 x1(j) = zero
              end do
              x1(i) = one
              do j = 1, m2
                 x2(j) = zero
              end do
              call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn,
           ! stopping when a nonzero projection is found
           do i = 1, m2
              do j = 1, m1
                 x1(j) = zero
              end do
              do j = 1, m2
                 x2(j) = zero
              end do
              x2(i) = one
              call stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_snrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_snrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           return
     end subroutine stdlib${ii}$_sorbdb5

     pure module subroutine stdlib${ii}$_dorbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! DORBDB5 orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then some other vector from the orthogonal complement
     !! is returned. This vector is chosen in an arbitrary but deterministic
     !! way.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(dp), intent(out) :: work(*)
           real(dp), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, j
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB5', -info )
              return
           end if
           ! project x onto the orthogonal complement of q
           call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, &
                     childinfo )
           ! if the projection is nonzero, then return
           if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) &
                     then
              return
           end if
           ! project each standard basis vector e_1,...,e_m1 in turn, stopping
           ! when a nonzero projection is found
           do i = 1, m1
              do j = 1, m1
                 x1(j) = zero
              end do
              x1(i) = one
              do j = 1, m2
                 x2(j) = zero
              end do
              call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn,
           ! stopping when a nonzero projection is found
           do i = 1, m2
              do j = 1, m1
                 x1(j) = zero
              end do
              do j = 1, m2
                 x2(j) = zero
              end do
              x2(i) = one
              call stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_dnrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_dnrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           return
     end subroutine stdlib${ii}$_dorbdb5

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$orbdb5( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! DORBDB5: orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then some other vector from the orthogonal complement
     !! is returned. This vector is chosen in an arbitrary but deterministic
     !! way.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(${rk}$), intent(out) :: work(*)
           real(${rk}$), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           
           ! Local Scalars 
           integer(${ik}$) :: childinfo, i, j
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB5', -info )
              return
           end if
           ! project x onto the orthogonal complement of q
           call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2, ldq2,work, lwork, &
                     childinfo )
           ! if the projection is nonzero, then return
           if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) &
                     then
              return
           end if
           ! project each standard basis vector e_1,...,e_m1 in turn, stopping
           ! when a nonzero projection is found
           do i = 1, m1
              do j = 1, m1
                 x1(j) = zero
              end do
              x1(i) = one
              do j = 1, m2
                 x2(j) = zero
              end do
              call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           ! project each standard basis vector e_(m1+1),...,e_(m1+m2) in turn,
           ! stopping when a nonzero projection is found
           do i = 1, m2
              do j = 1, m1
                 x1(j) = zero
              end do
              do j = 1, m2
                 x2(j) = zero
              end do
              x2(i) = one
              call stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
                        lwork, childinfo )
              if( stdlib${ii}$_${ri}$nrm2(m1,x1,incx1) /= zero.or. stdlib${ii}$_${ri}$nrm2(m2,x2,incx2) /= zero ) &
                        then
                 return
              end if
           end do
           return
     end subroutine stdlib${ii}$_${ri}$orbdb5

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_sorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! SORBDB6 orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then the zero vector is returned.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(sp), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(sp), intent(out) :: work(*)
           real(sp), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           ! Parameters 
           real(sp), parameter :: alphasq = 0.01_sp
           
           
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(sp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'SORBDB6', -info )
              return
           end if
           ! first, project x onto the orthogonal complement of q's column
           ! space
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_slassq( m2, x2, incx2, scl2, ssq2 )
           normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_sgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_sgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_sgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_sgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_slassq( m2, x2, incx2, scl2, ssq2 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if projection is sufficiently large in norm, then stop.
           ! if projection is zero, then stop.
           ! otherwise, project again.
           if( normsq2 >= alphasq*normsq1 ) then
              return
           end if
           if( normsq2 == zero ) then
              return
           end if
           normsq1 = normsq2
           do i = 1, n
              work(i) = zero
           end do
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_sgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_sgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_sgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_sgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_slassq( m1, x1, incx1, scl1, ssq1 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if second projection is sufficiently large in norm, then do
           ! nothing more. alternatively, if it shrunk significantly, then
           ! truncate it to zero.
           if( normsq2 < alphasq*normsq1 ) then
              do i = 1, m1
                 x1(i) = zero
              end do
              do i = 1, m2
                 x2(i) = zero
              end do
           end if
           return
     end subroutine stdlib${ii}$_sorbdb6

     pure module subroutine stdlib${ii}$_dorbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! DORBDB6 orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then the zero vector is returned.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(dp), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(dp), intent(out) :: work(*)
           real(dp), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           ! Parameters 
           real(dp), parameter :: alphasq = 0.01_dp
           
           
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(dp) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB6', -info )
              return
           end if
           ! first, project x onto the orthogonal complement of q's column
           ! space
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_dlassq( m2, x2, incx2, scl2, ssq2 )
           normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_dgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_dgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_dgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_dgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_dlassq( m2, x2, incx2, scl2, ssq2 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if projection is sufficiently large in norm, then stop.
           ! if projection is zero, then stop.
           ! otherwise, project again.
           if( normsq2 >= alphasq*normsq1 ) then
              return
           end if
           if( normsq2 == zero ) then
              return
           end if
           normsq1 = normsq2
           do i = 1, n
              work(i) = zero
           end do
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_dgemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_dgemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_dgemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_dgemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_dlassq( m1, x1, incx1, scl1, ssq1 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if second projection is sufficiently large in norm, then do
           ! nothing more. alternatively, if it shrunk significantly, then
           ! truncate it to zero.
           if( normsq2 < alphasq*normsq1 ) then
              do i = 1, m1
                 x1(i) = zero
              end do
              do i = 1, m2
                 x2(i) = zero
              end do
           end if
           return
     end subroutine stdlib${ii}$_dorbdb6

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$orbdb6( m1, m2, n, x1, incx1, x2, incx2, q1, ldq1, q2,ldq2, work, &
     !! DORBDB6: orthogonalizes the column vector
     !! X = [ X1 ]
     !! [ X2 ]
     !! with respect to the columns of
     !! Q = [ Q1 ] .
     !! [ Q2 ]
     !! The columns of Q must be orthonormal.
     !! If the projection is zero according to Kahan's "twice is enough"
     !! criterion, then the zero vector is returned.
               lwork, 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 
           integer(${ik}$), intent(in) :: incx1, incx2, ldq1, ldq2, lwork, m1, m2, n
           integer(${ik}$), intent(out) :: info
           ! Array Arguments 
           real(${rk}$), intent(in) :: q1(ldq1,*), q2(ldq2,*)
           real(${rk}$), intent(out) :: work(*)
           real(${rk}$), intent(inout) :: x1(*), x2(*)
        ! =====================================================================
           ! Parameters 
           real(${rk}$), parameter :: alphasq = 0.01_${rk}$
           
           
           
           ! Local Scalars 
           integer(${ik}$) :: i
           real(${rk}$) :: normsq1, normsq2, scl1, scl2, ssq1, ssq2
           ! Intrinsic Function 
           ! Executable Statements 
           ! test input arguments
           info = 0_${ik}$
           if( m1 < 0_${ik}$ ) then
              info = -1_${ik}$
           else if( m2 < 0_${ik}$ ) then
              info = -2_${ik}$
           else if( n < 0_${ik}$ ) then
              info = -3_${ik}$
           else if( incx1 < 1_${ik}$ ) then
              info = -5_${ik}$
           else if( incx2 < 1_${ik}$ ) then
              info = -7_${ik}$
           else if( ldq1 < max( 1_${ik}$, m1 ) ) then
              info = -9_${ik}$
           else if( ldq2 < max( 1_${ik}$, m2 ) ) then
              info = -11_${ik}$
           else if( lwork < n ) then
              info = -13_${ik}$
           end if
           if( info /= 0_${ik}$ ) then
              call stdlib${ii}$_xerbla( 'DORBDB6', -info )
              return
           end if
           ! first, project x onto the orthogonal complement of q's column
           ! space
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_${ri}$lassq( m2, x2, incx2, scl2, ssq2 )
           normsq1 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_${ri}$gemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_${ri}$gemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_${ri}$gemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_${ri}$gemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_${ri}$lassq( m2, x2, incx2, scl2, ssq2 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if projection is sufficiently large in norm, then stop.
           ! if projection is zero, then stop.
           ! otherwise, project again.
           if( normsq2 >= alphasq*normsq1 ) then
              return
           end if
           if( normsq2 == zero ) then
              return
           end if
           normsq1 = normsq2
           do i = 1, n
              work(i) = zero
           end do
           if( m1 == 0_${ik}$ ) then
              do i = 1, n
                 work(i) = zero
              end do
           else
              call stdlib${ii}$_${ri}$gemv( 'C', m1, n, one, q1, ldq1, x1, incx1, zero, work,1_${ik}$ )
           end if
           call stdlib${ii}$_${ri}$gemv( 'C', m2, n, one, q2, ldq2, x2, incx2, one, work, 1_${ik}$ )
           call stdlib${ii}$_${ri}$gemv( 'N', m1, n, negone, q1, ldq1, work, 1_${ik}$, one, x1,incx1 )
           call stdlib${ii}$_${ri}$gemv( 'N', m2, n, negone, q2, ldq2, work, 1_${ik}$, one, x2,incx2 )
           scl1 = zero
           ssq1 = one
           call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 )
           scl2 = zero
           ssq2 = one
           call stdlib${ii}$_${ri}$lassq( m1, x1, incx1, scl1, ssq1 )
           normsq2 = scl1**2_${ik}$*ssq1 + scl2**2_${ik}$*ssq2
           ! if second projection is sufficiently large in norm, then do
           ! nothing more. alternatively, if it shrunk significantly, then
           ! truncate it to zero.
           if( normsq2 < alphasq*normsq1 ) then
              do i = 1, m1
                 x1(i) = zero
              end do
              do i = 1, m2
                 x2(i) = zero
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ri}$orbdb6

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_slapmr( forwrd, m, n, x, ldx, k )
     !! SLAPMR rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(sp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           real(sp) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_slapmr

     pure module subroutine stdlib${ii}$_dlapmr( forwrd, m, n, x, ldx, k )
     !! DLAPMR rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(dp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           real(dp) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_dlapmr

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$lapmr( forwrd, m, n, x, ldx, k )
     !! DLAPMR: rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(${rk}$), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           real(${rk}$) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ri}$lapmr

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_clapmr( forwrd, m, n, x, ldx, k )
     !! CLAPMR rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(sp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           complex(sp) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_clapmr

     pure module subroutine stdlib${ii}$_zlapmr( forwrd, m, n, x, ldx, k )
     !! ZLAPMR rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(dp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           complex(dp) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_zlapmr

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$lapmr( forwrd, m, n, x, ldx, k )
     !! ZLAPMR: rearranges the rows of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(M) of the integers 1,...,M.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(K(I),*) is moved X(I,*) for I = 1,2,...,M.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(I,*) is moved to X(K(I),*) for I = 1,2,...,M.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(${ck}$), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, in, j, jj
           complex(${ck}$) :: temp
           ! Executable Statements 
           if( m<=1 )return
           do i = 1, m
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, m
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do jj = 1, n
                    temp = x( j, jj )
                    x( j, jj ) = x( in, jj )
                    x( in, jj ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, m
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do jj = 1, n
                    temp = x( i, jj )
                    x( i, jj ) = x( j, jj )
                    x( j, jj ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ci}$lapmr

#:endif
#:endfor



     pure module subroutine stdlib${ii}$_slapmt( forwrd, m, n, x, ldx, k )
     !! SLAPMT rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(sp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, j, in
           real(sp) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 100
                 k( i ) = -k( i )
                 j = k( i )
                 80 continue
                 if( j==i )go to 100
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 80
                 100 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_slapmt

     pure module subroutine stdlib${ii}$_dlapmt( forwrd, m, n, x, ldx, k )
     !! DLAPMT rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(dp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, in, j
           real(dp) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_dlapmt

#:for rk,rt,ri in REAL_KINDS_TYPES
#:if not rk in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ri}$lapmt( forwrd, m, n, x, ldx, k )
     !! DLAPMT: rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           real(${rk}$), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, in, j
           real(${rk}$) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ri}$lapmt

#:endif
#:endfor

     pure module subroutine stdlib${ii}$_clapmt( forwrd, m, n, x, ldx, k )
     !! CLAPMT rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(sp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, j, in
           complex(sp) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 100
                 k( i ) = -k( i )
                 j = k( i )
                 80 continue
                 if( j==i )go to 100
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 80
                 100 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_clapmt

     pure module subroutine stdlib${ii}$_zlapmt( forwrd, m, n, x, ldx, k )
     !! ZLAPMT rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(dp), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, in, j
           complex(dp) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_zlapmt

#:for ck,ct,ci in CMPLX_KINDS_TYPES
#:if not ck in ["sp","dp"]
     pure module subroutine stdlib${ii}$_${ci}$lapmt( forwrd, m, n, x, ldx, k )
     !! ZLAPMT: rearranges the columns of the M by N matrix X as specified
     !! by the permutation K(1),K(2),...,K(N) of the integers 1,...,N.
     !! If FORWRD = .TRUE.,  forward permutation:
     !! X(*,K(J)) is moved X(*,J) for J = 1,2,...,N.
     !! If FORWRD = .FALSE., backward permutation:
     !! X(*,J) is moved to X(*,K(J)) for J = 1,2,...,N.
        ! -- lapack auxiliary routine --
        ! -- lapack is a software package provided by univ. of tennessee,    --
        ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..--
           use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone
           ! Scalar Arguments 
           logical(lk), intent(in) :: forwrd
           integer(${ik}$), intent(in) :: ldx, m, n
           ! Array Arguments 
           integer(${ik}$), intent(inout) :: k(*)
           complex(${ck}$), intent(inout) :: x(ldx,*)
        ! =====================================================================
           ! Local Scalars 
           integer(${ik}$) :: i, ii, in, j
           complex(${ck}$) :: temp
           ! Executable Statements 
           if( n<=1 )return
           do i = 1, n
              k( i ) = -k( i )
           end do
           if( forwrd ) then
              ! forward permutation
              do i = 1, n
                 if( k( i )>0 )go to 40
                 j = i
                 k( j ) = -k( j )
                 in = k( j )
                 20 continue
                 if( k( in )>0 )go to 40
                 do ii = 1, m
                    temp = x( ii, j )
                    x( ii, j ) = x( ii, in )
                    x( ii, in ) = temp
                 end do
                 k( in ) = -k( in )
                 j = in
                 in = k( in )
                 go to 20
                 40 continue
              end do
           else
              ! backward permutation
              do i = 1, n
                 if( k( i )>0 )go to 80
                 k( i ) = -k( i )
                 j = k( i )
                 60 continue
                 if( j==i )go to 80
                 do ii = 1, m
                    temp = x( ii, i )
                    x( ii, i ) = x( ii, j )
                    x( ii, j ) = temp
                 end do
                 k( j ) = -k( j )
                 j = k( j )
                 go to 60
                 80 continue
              end do
           end if
           return
     end subroutine stdlib${ii}$_${ci}$lapmt

#:endif
#:endfor


#:endfor
end submodule stdlib_lapack_cosine_sine2