#:include "common.fypp" submodule(stdlib_lapack_eig_svd_lsq) stdlib_lapack_lsq_aux implicit none contains #:for ik,it,ii in LINALG_INT_KINDS_TYPES pure module subroutine stdlib${ii}$_slaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! SLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then SLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(sp), intent(out) :: c, s, sestpr real(sp), intent(in) :: gamma, sest ! Array Arguments real(sp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(sp) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_slamch( 'EPSILON' ) alpha = stdlib${ii}$_sdot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_slaic1 pure module subroutine stdlib${ii}$_dlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! DLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then DLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(dp), intent(out) :: c, s, sestpr real(dp), intent(in) :: gamma, sest ! Array Arguments real(dp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(dp) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_dlamch( 'EPSILON' ) alpha = stdlib${ii}$_ddot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_dlaic1 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$laic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! DLAIC1: applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then DLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**T gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**T and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ alpha ] !! [ gamma ] !! where alpha = x**T*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${rk}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(${rk}$), intent(out) :: c, s, sestpr real(${rk}$), intent(in) :: gamma, sest ! Array Arguments real(${rk}$), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(${rk}$) :: absalp, absest, absgam, alpha, b, cosine, eps, norma, s1, s2, sine, t, & test, tmp, zeta1, zeta2 ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_${ri}$lamch( 'EPSILON' ) alpha = stdlib${ii}$_${ri}$dot( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 s = sqrt( one+tmp*tmp ) sestpr = s2*s c = ( gamma / s2 ) / s s = sign( one, alpha ) / s else tmp = s2 / s1 c = sqrt( one+tmp*tmp ) sestpr = s1*c s = ( alpha / s1 ) / c c = sign( one, gamma ) / c end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = c / ( b+sqrt( b*b+c ) ) else t = sqrt( b*b+c ) - b end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -gamma cosine = alpha end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = sqrt( s*s+c*c ) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 c = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / c ) s = -( gamma / s2 ) / c c = sign( one, alpha ) / c else tmp = s2 / s1 s = sqrt( one+tmp*tmp ) sestpr = absest / s c = ( alpha / s1 ) / s s = -sign( one, gamma ) / s end if return else ! normal case zeta1 = alpha / absest zeta2 = gamma / absest norma = max( one+zeta1*zeta1+abs( zeta1*zeta2 ),abs( zeta1*zeta2 )+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = c / ( b+sqrt( abs( b*b-c ) ) ) sine = zeta1 / ( one-t ) cosine = -zeta2 / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -zeta1 / t cosine = -zeta2 / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = sqrt( sine*sine+cosine*cosine ) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_${ri}$laic1 #:endif #:endfor pure module subroutine stdlib${ii}$_claic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! CLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then CLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H*w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_sp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(sp), intent(in) :: sest real(sp), intent(out) :: sestpr complex(sp), intent(out) :: c, s complex(sp), intent(in) :: gamma ! Array Arguments complex(sp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(sp) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(sp) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_slamch( 'EPSILON' ) alpha = stdlib${ii}$_cdotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=sp) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=sp) else t = real( sqrt( b*b+c ) - b,KIND=sp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=sp) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=sp) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=sp) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = real( -c / ( b+sqrt( b*b+c ) ),KIND=sp) else t = real( b - sqrt( b*b+c ),KIND=sp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=sp) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_claic1 pure module subroutine stdlib${ii}$_zlaic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! ZLAIC1 applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then ZLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H * w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_dp, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(dp), intent(in) :: sest real(dp), intent(out) :: sestpr complex(dp), intent(out) :: c, s complex(dp), intent(in) :: gamma ! Array Arguments complex(dp), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(dp) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(dp) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_dlamch( 'EPSILON' ) alpha = stdlib${ii}$_zdotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=dp) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=dp) else t = real( sqrt( b*b+c ) - b,KIND=dp) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=dp) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=dp) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=dp) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=dp) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_zlaic1 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$laic1( job, j, x, sest, w, gamma, sestpr, s, c ) !! ZLAIC1: applies one step of incremental condition estimation in !! its simplest version: !! Let x, twonorm(x) = 1, be an approximate singular vector of an j-by-j !! lower triangular matrix L, such that !! twonorm(L*x) = sest !! Then ZLAIC1 computes sestpr, s, c such that !! the vector !! [ s*x ] !! xhat = [ c ] !! is an approximate singular vector of !! [ L 0 ] !! Lhat = [ w**H gamma ] !! in the sense that !! twonorm(Lhat*xhat) = sestpr. !! Depending on JOB, an estimate for the largest or smallest singular !! value is computed. !! Note that [s c]**H and sestpr**2 is an eigenpair of the system !! diag(sest*sest, 0) + [alpha gamma] * [ conjg(alpha) ] !! [ conjg(gamma) ] !! where alpha = x**H * w. ! -- lapack auxiliary routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: j, job real(${ck}$), intent(in) :: sest real(${ck}$), intent(out) :: sestpr complex(${ck}$), intent(out) :: c, s complex(${ck}$), intent(in) :: gamma ! Array Arguments complex(${ck}$), intent(in) :: w(j), x(j) ! ===================================================================== ! Local Scalars real(${ck}$) :: absalp, absest, absgam, b, eps, norma, s1, s2, scl, t, test, tmp, zeta1, & zeta2 complex(${ck}$) :: alpha, cosine, sine ! Intrinsic Functions ! Executable Statements eps = stdlib${ii}$_${c2ri(ci)}$lamch( 'EPSILON' ) alpha = stdlib${ii}$_${ci}$dotc( j, x, 1_${ik}$, w, 1_${ik}$ ) absalp = abs( alpha ) absgam = abs( gamma ) absest = abs( sest ) if( job==1_${ik}$ ) then ! estimating largest singular value ! special cases if( sest==zero ) then s1 = max( absgam, absalp ) if( s1==zero ) then s = zero c = one sestpr = zero else s = alpha / s1 c = gamma / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=${ck}$) s = s / tmp c = c / tmp sestpr = s1*tmp end if return else if( absgam<=eps*absest ) then s = one c = zero tmp = max( absest, absalp ) s1 = absest / tmp s2 = absalp / tmp sestpr = tmp*sqrt( s1*s1+s2*s2 ) return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = one c = zero sestpr = s2 else s = zero c = one sestpr = s1 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = s2*scl s = ( alpha / s2 ) / scl c = ( gamma / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = s1*scl s = ( alpha / s1 ) / scl c = ( gamma / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest b = ( one-zeta1*zeta1-zeta2*zeta2 )*half c = zeta1*zeta1 if( b>zero ) then t = real( c / ( b+sqrt( b*b+c ) ),KIND=${ck}$) else t = real( sqrt( b*b+c ) - b,KIND=${ck}$) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=${ck}$) s = sine / tmp c = cosine / tmp sestpr = sqrt( t+one )*absest return end if else if( job==2_${ik}$ ) then ! estimating smallest singular value ! special cases if( sest==zero ) then sestpr = zero if( max( absgam, absalp )==zero ) then sine = one cosine = zero else sine = -conjg( gamma ) cosine = conjg( alpha ) end if s1 = max( abs( sine ), abs( cosine ) ) s = sine / s1 c = cosine / s1 tmp = real( sqrt( s*conjg( s )+c*conjg( c ) ),KIND=${ck}$) s = s / tmp c = c / tmp return else if( absgam<=eps*absest ) then s = zero c = one sestpr = absgam return else if( absalp<=eps*absest ) then s1 = absgam s2 = absest if( s1<=s2 ) then s = zero c = one sestpr = s1 else s = one c = zero sestpr = s2 end if return else if( absest<=eps*absalp .or. absest<=eps*absgam ) then s1 = absgam s2 = absalp if( s1<=s2 ) then tmp = s1 / s2 scl = sqrt( one+tmp*tmp ) sestpr = absest*( tmp / scl ) s = -( conjg( gamma ) / s2 ) / scl c = ( conjg( alpha ) / s2 ) / scl else tmp = s2 / s1 scl = sqrt( one+tmp*tmp ) sestpr = absest / scl s = -( conjg( gamma ) / s1 ) / scl c = ( conjg( alpha ) / s1 ) / scl end if return else ! normal case zeta1 = absalp / absest zeta2 = absgam / absest norma = max( one+zeta1*zeta1+zeta1*zeta2,zeta1*zeta2+zeta2*zeta2 ) ! see if root is closer to zero or to one test = one + two*( zeta1-zeta2 )*( zeta1+zeta2 ) if( test>=zero ) then ! root is close to zero, compute directly b = ( zeta1*zeta1+zeta2*zeta2+one )*half c = zeta2*zeta2 t = real( c / ( b+sqrt( abs( b*b-c ) ) ),KIND=${ck}$) sine = ( alpha / absest ) / ( one-t ) cosine = -( gamma / absest ) / t sestpr = sqrt( t+four*eps*eps*norma )*absest else ! root is closer to one, shift by that amount b = ( zeta2*zeta2+zeta1*zeta1-one )*half c = zeta1*zeta1 if( b>=zero ) then t = -c / ( b+sqrt( b*b+c ) ) else t = b - sqrt( b*b+c ) end if sine = -( alpha / absest ) / t cosine = -( gamma / absest ) / ( one+t ) sestpr = sqrt( one+t+four*eps*eps*norma )*absest end if tmp = real( sqrt( sine * conjg( sine )+ cosine * conjg( cosine ) ),KIND=${ck}$) s = sine / tmp c = cosine / tmp return end if end if return end subroutine stdlib${ii}$_${ci}$laic1 #:endif #:endfor pure module subroutine stdlib${ii}$_slals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! SLALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, 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) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(sp), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: bx(ldbx,*), work(*) real(sp), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, m, n, nlp1 real(sp) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_srot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_scopy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_scopy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_scopy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_sscal( nrhs, negone, b, ldb ) end if else loop_50: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then work( j ) = zero else work( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_slamc3( poles( i, 2_${ik}$ ), dsigj & )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_slamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do work( 1_${ik}$ ) = negone temp = stdlib${ii}$_snrm2( k, work, 1_${ik}$ ) call stdlib${ii}$_sgemv( 'T', k, nrhs, one, bx, ldbx, work, 1_${ik}$, zero,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_slascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_50 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_slacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_scopy( nrhs, b, ldb, bx, ldbx ) else do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then work( j ) = zero else work( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_slamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i, & 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_slamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) )& /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do call stdlib${ii}$_sgemv( 'T', k, nrhs, one, b, ldb, work, 1_${ik}$, zero,bx( j, 1_${ik}$ ), ldbx ) end do end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_scopy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_srot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_slacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb, bx( k+1, 1_${ik}$ & ),ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_scopy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_scopy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_scopy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_srot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_slals0 pure module subroutine stdlib${ii}$_dlals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! DLALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, 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) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(dp), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(dp), intent(inout) :: b(ldb,*) real(dp), intent(out) :: bx(ldbx,*), work(*) real(dp), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, m, n, nlp1 real(dp) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_drot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_dcopy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_dcopy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_dcopy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_dscal( nrhs, negone, b, ldb ) end if else loop_50: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then work( j ) = zero else work( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_dlamc3( poles( i, 2_${ik}$ ), dsigj & )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_dlamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do work( 1_${ik}$ ) = negone temp = stdlib${ii}$_dnrm2( k, work, 1_${ik}$ ) call stdlib${ii}$_dgemv( 'T', k, nrhs, one, bx, ldbx, work, 1_${ik}$, zero,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_dlascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_50 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_dlacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_dcopy( nrhs, b, ldb, bx, ldbx ) else do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then work( j ) = zero else work( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_dlamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i, & 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_dlamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) )& /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do call stdlib${ii}$_dgemv( 'T', k, nrhs, one, b, ldb, work, 1_${ik}$, zero,bx( j, 1_${ik}$ ), ldbx ) end do end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_dcopy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_drot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_dlacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb, bx( k+1, 1_${ik}$ & ),ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_dcopy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_dcopy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_dcopy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_drot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_dlals0 #:for rk,rt,ri in REAL_KINDS_TYPES #:if not rk in ["sp","dp"] pure module subroutine stdlib${ii}$_${ri}$lals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! DLALS0: applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, work, 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) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(${rk}$), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(${rk}$), intent(inout) :: b(ldb,*) real(${rk}$), intent(out) :: bx(ldbx,*), work(*) real(${rk}$), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, m, n, nlp1 real(${rk}$) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'DLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_${ri}$rot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_${ri}$copy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_${ri}$copy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_${ri}$scal( nrhs, negone, b, ldb ) end if else loop_50: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then work( j ) = zero else work( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_${ri}$lamc3( poles( i, 2_${ik}$ ), dsigj & )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then work( i ) = zero else work( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_${ri}$lamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do work( 1_${ik}$ ) = negone temp = stdlib${ii}$_${ri}$nrm2( k, work, 1_${ik}$ ) call stdlib${ii}$_${ri}$gemv( 'T', k, nrhs, one, bx, ldbx, work, 1_${ik}$, zero,b( j, 1_${ik}$ ), ldb ) call stdlib${ii}$_${ri}$lascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_50 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_${ri}$lacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( nrhs, b, ldb, bx, ldbx ) else do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then work( j ) = zero else work( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_${ri}$lamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i, & 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then work( i ) = zero else work( i ) = z( j ) / ( stdlib${ii}$_${ri}$lamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) )& /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do call stdlib${ii}$_${ri}$gemv( 'T', k, nrhs, one, b, ldb, work, 1_${ik}$, zero,bx( j, 1_${ik}$ ), ldbx ) end do end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_${ri}$rot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_${ri}$lacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb, bx( k+1, 1_${ik}$ & ),ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_${ri}$copy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_${ri}$copy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_${ri}$copy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_${ri}$rot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb, & givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_${ri}$lals0 #:endif #:endfor pure module subroutine stdlib${ii}$_clals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! CLALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, rwork, 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) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(sp), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(sp), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) real(sp), intent(out) :: rwork(*) complex(sp), intent(inout) :: b(ldb,*) complex(sp), intent(out) :: bx(ldbx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jcol, jrow, m, n, nlp1 real(sp) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'CLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_csrot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_ccopy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_ccopy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_ccopy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_csscal( nrhs, negone, b, ldb ) end if else loop_100: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then rwork( j ) = zero else rwork( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_slamc3( poles( i, 2_${ik}$ ), & dsigj )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_slamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do rwork( 1_${ik}$ ) = negone temp = stdlib${ii}$_snrm2( k, rwork, 1_${ik}$ ) ! since b and bx are complex, the following call to stdlib${ii}$_sgemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_sgemv( 't', k, nrhs, one, bx, ldbx, work, 1, zero, ! $ b( j, 1 ), ldb ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( bx( jrow, jcol ),KIND=sp) end do end do call stdlib${ii}$_sgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( bx( jrow, jcol ) ) end do end do call stdlib${ii}$_sgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs b( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=sp) end do call stdlib${ii}$_clascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_100 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_clacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_ccopy( nrhs, b, ldb, bx, ldbx ) else loop_180: do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then rwork( j ) = zero else rwork( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_slamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i,& 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_slamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) & ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do ! since b and bx are complex, the following call to stdlib${ii}$_sgemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_sgemv( 't', k, nrhs, one, b, ldb, work, 1, zero, ! $ bx( j, 1 ), ldbx ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( b( jrow, jcol ),KIND=sp) end do end do call stdlib${ii}$_sgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_sgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs bx( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=sp) end do end do loop_180 end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_ccopy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_csrot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_clacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb,bx( k+1, 1_${ik}$ )& , ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_ccopy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_ccopy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_ccopy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_csrot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_clals0 pure module subroutine stdlib${ii}$_zlals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! ZLALS0 applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, rwork, 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) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(dp), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(dp), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) real(dp), intent(out) :: rwork(*) complex(dp), intent(inout) :: b(ldb,*) complex(dp), intent(out) :: bx(ldbx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jcol, jrow, m, n, nlp1 real(dp) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_zdrot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_zcopy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_zcopy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_zcopy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_zdscal( nrhs, negone, b, ldb ) end if else loop_100: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then rwork( j ) = zero else rwork( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_dlamc3( poles( i, 2_${ik}$ ), & dsigj )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_dlamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do rwork( 1_${ik}$ ) = negone temp = stdlib${ii}$_dnrm2( k, rwork, 1_${ik}$ ) ! since b and bx are complex, the following call to stdlib${ii}$_dgemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_dgemv( 't', k, nrhs, one, bx, ldbx, work, 1, zero, ! $ b( j, 1 ), ldb ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( bx( jrow, jcol ),KIND=dp) end do end do call stdlib${ii}$_dgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( bx( jrow, jcol ) ) end do end do call stdlib${ii}$_dgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs b( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=dp) end do call stdlib${ii}$_zlascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_100 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_zlacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_zcopy( nrhs, b, ldb, bx, ldbx ) else loop_180: do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then rwork( j ) = zero else rwork( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_dlamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i,& 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_dlamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) & ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do ! since b and bx are complex, the following call to stdlib${ii}$_dgemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_dgemv( 't', k, nrhs, one, b, ldb, work, 1, zero, ! $ bx( j, 1 ), ldbx ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( b( jrow, jcol ),KIND=dp) end do end do call stdlib${ii}$_dgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_dgemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs bx( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=dp) end do end do loop_180 end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_zcopy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_zdrot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_zlacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb, bx( k+1, 1_${ik}$ & ),ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_zcopy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_zcopy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_zcopy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_zdrot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_zlals0 #:for ck,ct,ci in CMPLX_KINDS_TYPES #:if not ck in ["sp","dp"] pure module subroutine stdlib${ii}$_${ci}$lals0( icompq, nl, nr, sqre, nrhs, b, ldb, bx, ldbx,perm, givptr, & !! ZLALS0: applies back the multiplying factors of either the left or the !! right singular vector matrix of a diagonal matrix appended by a row !! to the right hand side matrix B in solving the least squares problem !! using the divide-and-conquer SVD approach. !! For the left singular vector matrix, three types of orthogonal !! matrices are involved: !! (1L) Givens rotations: the number of such rotations is GIVPTR; the !! pairs of columns/rows they were applied to are stored in GIVCOL; !! and the C- and S-values of these rotations are stored in GIVNUM. !! (2L) Permutation. The (NL+1)-st row of B is to be moved to the first !! row, and for J=2:N, PERM(J)-th row of B is to be moved to the !! J-th row. !! (3L) The left singular vector matrix of the remaining matrix. !! For the right singular vector matrix, four types of orthogonal !! matrices are involved: !! (1R) The right singular vector matrix of the remaining matrix. !! (2R) If SQRE = 1, one extra Givens rotation to generate the right !! null space. !! (3R) The inverse transformation of (2L). !! (4R) The inverse transformation of (1L). givcol, ldgcol, givnum, ldgnum,poles, difl, difr, z, k, c, s, rwork, info ) ! -- lapack computational routine -- ! -- lapack is a software package provided by univ. of tennessee, -- ! -- univ. of california berkeley, univ. of colorado denver and nag ltd..-- use stdlib_blas_constants_${ck}$, only: negone, zero, half, one, two, three, four, eight, ten, czero, chalf, cone, cnegone ! Scalar Arguments integer(${ik}$), intent(in) :: givptr, icompq, k, ldb, ldbx, ldgcol, ldgnum, nl, nr, nrhs,& sqre integer(${ik}$), intent(out) :: info real(${ck}$), intent(in) :: c, s ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), perm(*) real(${ck}$), intent(in) :: difl(*), difr(ldgnum,*), givnum(ldgnum,*), poles(ldgnum,*), z(& *) real(${ck}$), intent(out) :: rwork(*) complex(${ck}$), intent(inout) :: b(ldb,*) complex(${ck}$), intent(out) :: bx(ldbx,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, j, jcol, jrow, m, n, nlp1 real(${ck}$) :: diflj, difrj, dj, dsigj, dsigjp, temp ! Intrinsic Functions ! Executable Statements ! test the input parameters. info = 0_${ik}$ n = nl + nr + 1_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( nl<1_${ik}$ ) then info = -2_${ik}$ else if( nr<1_${ik}$ ) then info = -3_${ik}$ else if( ( sqre<0_${ik}$ ) .or. ( sqre>1_${ik}$ ) ) then info = -4_${ik}$ else if( nrhs<1_${ik}$ ) then info = -5_${ik}$ else if( ldb<n ) then info = -7_${ik}$ else if( ldbx<n ) then info = -9_${ik}$ else if( givptr<0_${ik}$ ) then info = -11_${ik}$ else if( ldgcol<n ) then info = -13_${ik}$ else if( ldgnum<n ) then info = -15_${ik}$ else if( k<1_${ik}$ ) then info = -20_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'ZLALS0', -info ) return end if m = n + sqre nlp1 = nl + 1_${ik}$ if( icompq==0_${ik}$ ) then ! apply back orthogonal transformations from the left. ! step (1l): apply back the givens rotations performed. do i = 1, givptr call stdlib${ii}$_${ci}$drot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),givnum( i, 1_${ik}$ ) ) end do ! step (2l): permute rows of b. call stdlib${ii}$_${ci}$copy( nrhs, b( nlp1, 1_${ik}$ ), ldb, bx( 1_${ik}$, 1_${ik}$ ), ldbx ) do i = 2, n call stdlib${ii}$_${ci}$copy( nrhs, b( perm( i ), 1_${ik}$ ), ldb, bx( i, 1_${ik}$ ), ldbx ) end do ! step (3l): apply the inverse of the left singular vector ! matrix to bx. if( k==1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( nrhs, bx, ldbx, b, ldb ) if( z( 1_${ik}$ )<zero ) then call stdlib${ii}$_${ci}$dscal( nrhs, negone, b, ldb ) end if else loop_100: do j = 1, k diflj = difl( j ) dj = poles( j, 1_${ik}$ ) dsigj = -poles( j, 2_${ik}$ ) if( j<k ) then difrj = -difr( j, 1_${ik}$ ) dsigjp = -poles( j+1, 2_${ik}$ ) end if if( ( z( j )==zero ) .or. ( poles( j, 2_${ik}$ )==zero ) )then rwork( j ) = zero else rwork( j ) = -poles( j, 2_${ik}$ )*z( j ) / diflj /( poles( j, 2_${ik}$ )+dj ) end if do i = 1, j - 1 if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_${c2ri(ci)}$lamc3( poles( i, 2_${ik}$ ), & dsigj )-diflj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do do i = j + 1, k if( ( z( i )==zero ) .or.( poles( i, 2_${ik}$ )==zero ) ) then rwork( i ) = zero else rwork( i ) = poles( i, 2_${ik}$ )*z( i ) /( stdlib${ii}$_${c2ri(ci)}$lamc3( poles( i, 2_${ik}$ ), & dsigjp )+difrj ) / ( poles( i, 2_${ik}$ )+dj ) end if end do rwork( 1_${ik}$ ) = negone temp = stdlib${ii}$_${c2ri(ci)}$nrm2( k, rwork, 1_${ik}$ ) ! since b and bx are complex, the following call to stdlib${ii}$_${c2ri(ci)}$gemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_${c2ri(ci)}$gemv( 't', k, nrhs, one, bx, ldbx, work, 1, zero, ! $ b( j, 1 ), ldb ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( bx( jrow, jcol ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( bx( jrow, jcol ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs b( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=${ck}$) end do call stdlib${ii}$_${ci}$lascl( 'G', 0_${ik}$, 0_${ik}$, temp, one, 1_${ik}$, nrhs, b( j, 1_${ik}$ ),ldb, info ) end do loop_100 end if ! move the deflated rows of bx to b also. if( k<max( m, n ) )call stdlib${ii}$_${ci}$lacpy( 'A', n-k, nrhs, bx( k+1, 1_${ik}$ ), ldbx,b( k+1, 1_${ik}$ & ), ldb ) else ! apply back the right orthogonal transformations. ! step (1r): apply back the new right singular vector matrix ! to b. if( k==1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( nrhs, b, ldb, bx, ldbx ) else loop_180: do j = 1, k dsigj = poles( j, 2_${ik}$ ) if( z( j )==zero ) then rwork( j ) = zero else rwork( j ) = -z( j ) / difl( j ) /( dsigj+poles( j, 1_${ik}$ ) ) / difr( j, 2_${ik}$ ) end if do i = 1, j - 1 if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_${c2ri(ci)}$lamc3( dsigj, -poles( i+1,2_${ik}$ ) )-difr( i,& 1_${ik}$ ) ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do do i = j + 1, k if( z( j )==zero ) then rwork( i ) = zero else rwork( i ) = z( j ) / ( stdlib${ii}$_${c2ri(ci)}$lamc3( dsigj, -poles( i,2_${ik}$ ) )-difl( i ) & ) /( dsigj+poles( i, 1_${ik}$ ) ) / difr( i, 2_${ik}$ ) end if end do ! since b and bx are complex, the following call to stdlib${ii}$_${c2ri(ci)}$gemv ! is performed in two steps (real and imaginary parts). ! call stdlib${ii}$_${c2ri(ci)}$gemv( 't', k, nrhs, one, b, ldb, work, 1, zero, ! $ bx( j, 1 ), ldbx ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = real( b( jrow, jcol ),KIND=${ck}$) end do end do call stdlib${ii}$_${c2ri(ci)}$gemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k ), 1_${ik}$ ) i = k + nrhs*2_${ik}$ do jcol = 1, nrhs do jrow = 1, k i = i + 1_${ik}$ rwork( i ) = aimag( b( jrow, jcol ) ) end do end do call stdlib${ii}$_${c2ri(ci)}$gemv( 'T', k, nrhs, one, rwork( 1_${ik}$+k+nrhs*2_${ik}$ ), k,rwork( 1_${ik}$ ), 1_${ik}$, & zero, rwork( 1_${ik}$+k+nrhs ), 1_${ik}$ ) do jcol = 1, nrhs bx( j, jcol ) = cmplx( rwork( jcol+k ),rwork( jcol+k+nrhs ),KIND=${ck}$) end do end do loop_180 end if ! step (2r): if sqre = 1, apply back the rotation that is ! related to the right null space of the subproblem. if( sqre==1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( nrhs, b( m, 1_${ik}$ ), ldb, bx( m, 1_${ik}$ ), ldbx ) call stdlib${ii}$_${ci}$drot( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, bx( m, 1_${ik}$ ), ldbx, c, s ) end if if( k<max( m, n ) )call stdlib${ii}$_${ci}$lacpy( 'A', n-k, nrhs, b( k+1, 1_${ik}$ ), ldb, bx( k+1, 1_${ik}$ & ),ldbx ) ! step (3r): permute rows of b. call stdlib${ii}$_${ci}$copy( nrhs, bx( 1_${ik}$, 1_${ik}$ ), ldbx, b( nlp1, 1_${ik}$ ), ldb ) if( sqre==1_${ik}$ ) then call stdlib${ii}$_${ci}$copy( nrhs, bx( m, 1_${ik}$ ), ldbx, b( m, 1_${ik}$ ), ldb ) end if do i = 2, n call stdlib${ii}$_${ci}$copy( nrhs, bx( i, 1_${ik}$ ), ldbx, b( perm( i ), 1_${ik}$ ), ldb ) end do ! step (4r): apply back the givens rotations performed. do i = givptr, 1, -1 call stdlib${ii}$_${ci}$drot( nrhs, b( givcol( i, 2_${ik}$ ), 1_${ik}$ ), ldb,b( givcol( i, 1_${ik}$ ), 1_${ik}$ ), ldb,& givnum( i, 2_${ik}$ ),-givnum( i, 1_${ik}$ ) ) end do end if return end subroutine stdlib${ii}$_${ci}$lals0 #:endif #:endfor pure module subroutine stdlib${ii}$_slalsa( icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u,ldu, vt, k, difl,& !! SLALSA is an itermediate step in solving the least squares problem !! by computing the SVD of the coefficient matrix in compact form (The !! singular vectors are computed as products of simple orthorgonal !! matrices.). !! If ICOMPQ = 0, SLALSA applies the inverse of the left singular vector !! matrix of an upper bidiagonal matrix to the right hand side; and if !! ICOMPQ = 1, SLALSA applies the right singular vector matrix to the !! right hand side. The singular vector matrices were generated in !! compact form by SLALSA. difr, z, poles, givptr,givcol, ldgcol, perm, givnum, c, s, work,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 integer(${ik}$), intent(in) :: icompq, ldb, ldbx, ldgcol, ldu, n, nrhs, smlsiz integer(${ik}$), intent(out) :: info ! Array Arguments integer(${ik}$), intent(in) :: givcol(ldgcol,*), givptr(*), k(*), perm(ldgcol,*) integer(${ik}$), intent(out) :: iwork(*) real(sp), intent(inout) :: b(ldb,*) real(sp), intent(out) :: bx(ldbx,*), work(*) real(sp), intent(in) :: c(*), difl(ldu,*), difr(ldu,*), givnum(ldu,*), poles(ldu,*), s(& *), u(ldu,*), vt(ldu,*), z(ldu,*) ! ===================================================================== ! Local Scalars integer(${ik}$) :: i, i1, ic, im1, inode, j, lf, ll, lvl, lvl2, nd, ndb1, ndiml, ndimr, & nl, nlf, nlp1, nlvl, nr, nrf, nrp1, sqre ! Executable Statements ! test the input parameters. info = 0_${ik}$ if( ( icompq<0_${ik}$ ) .or. ( icompq>1_${ik}$ ) ) then info = -1_${ik}$ else if( smlsiz<3_${ik}$ ) then info = -2_${ik}$ else if( n<smlsiz ) then info = -3_${ik}$ else if( nrhs<1_${ik}$ ) then info = -4_${ik}$ else if( ldb<n ) then info = -6_${ik}$ else if( ldbx<n ) then info = -8_${ik}$ else if( ldu<n ) then info = -10_${ik}$ else if( ldgcol<n ) then info = -19_${ik}$ end if if( info/=0_${ik}$ ) then call stdlib${ii}$_xerbla( 'SLALSA', -info ) return end if ! book-keeping and setting up the computation tree. inode = 1_${ik}$ ndiml = inode + n ndimr = ndiml + n call stdlib${ii}$_slasdt( n, nlvl, nd, iwork( inode ), iwork( ndiml ),iwork( ndimr ), smlsiz & ) ! the following code applies back the left singular vector factors. ! for applying back the right singular vector factors, go to 50. if( icompq==1_${ik}$ ) then go to 50 end if ! the nodes on the bottom level of the tree were solved ! by stdlib${ii}$_slasdq. the corresponding left and right singular vector ! matrices are in explicit form. first apply back the left ! singular vector matrices. ndb1 = ( nd+1 ) / 2_${ik}$ do i = ndb1, nd ! ic : center row of each node ! nl : number of rows of left subproblem ! nr : number of rows of right subproblem ! nlf: starting row of the left subproblem ! nrf: starting row of the right subproblem i1 = i - 1_${ik}$ ic = iwork( inode+i1 ) nl = iwork( ndiml+i1 ) nr = iwork( ndimr+i1 ) nlf = ic - nl nrf = ic + 1_${ik}$ call stdlib${ii}$_sgemm( 'T', 'N', nl, nrhs, nl, one, u( nlf, 1_${ik}$ ), ldu,b( nlf, 1_${ik}$ ), ldb, & zero, bx( nlf, 1_${ik}$ ), ldbx ) call stdlib${ii}$_sgemm( 'T', 'N', nr, nrhs, nr, one, u( nrf, 1_${ik}$ ), ldu,b( nrf, 1_${ik}$ ), ldb, & zero, bx( nrf, 1_${ik}$ ), ldbx ) end do ! next copy the rows of b that correspond to unchanged rows ! in the bidiagonal matrix to bx. do i = 1, nd ic = iwork( inode+i-1 ) call stdlib${ii}$_scopy( nrhs, b( ic, 1_${ik}$ ), ldb, bx( ic, 1_${ik}$ ), ldbx ) end do ! finally go through the left singular vector matrices of all ! the other subproblems bottom-up on the tree. j = 2_${ik}$**nlvl sqre = 0_${ik}$ do lvl = nlvl, 1, -1 lvl2 = 2_${ik}$*lvl - 1_${ik}$ ! find the first node lf and last node ll on ! the current level lvl if( lvl==1_${ik}$ ) then lf = 1_${ik}$ ll = 1_${ik}$ else lf = 2_${ik}$**( lvl-1 ) ll = 2_${ik}$*lf - 1_${ik}$ end if do i = lf, ll im1 = i - 1_${ik}$ ic = iwork( inode+im1 ) nl = iwork( ndiml+im1 ) nr = iwork( ndimr+im1 ) nlf = ic - nl nrf = ic + 1_${ik}$ j = j - 1_${ik}$ call stdlib${ii}$_slals0( icompq, nl, nr, sqre, nrhs, bx( nlf, 1_${ik}$ ), ldbx,b( nlf, 1_${ik}$ ), & ldb, perm( nlf, lvl ),givptr( j ), givcol( nlf, lvl2 ), ldgcol,givnum( nlf, lvl2 & ), ldu, poles( nlf, lvl2 ),difl( nlf, lvl ), difr( nlf, lvl2 ),z( nlf, lvl ), k( & j ), c( j ), s( j ), work,info ) end do end do go to 90 ! icompq = 1: applying back the right singular vector factors. 50 continue ! first now go through the right singular vector matrices of all ! the tree nodes top-down. j = 0_${ik}$ loop_70: do lvl = 1, nlvl lvl2 = 2_${ik}$*lvl - 1_${ik}$ ! find the first node lf and last node ll on ! the current level lvl. if( lvl==1_${ik}$ ) then lf = 1_${ik}$ ll = 1_${ik}$ else lf = 2_${ik}$**( lvl-1 ) ll = 2_${ik}$*lf - 1_${ik}$ end if do i = ll, lf, -1 im1 = i - 1_${ik}$ ic = iwork( inode+im1 ) nl = iwork( ndiml+im1 ) nr = iwork( ndimr+im1 ) nlf = ic - nl nrf = ic + 1_${ik}$ if( i==ll ) then sqre = 0_${ik}$ else sqre = 1_${ik}$ end if j = j + 1_${ik}$ call stdlib${ii}$_slals0( icompq, nl, nr, sqre, nrhs, b( nlf, 1_${ik}$ ), ldb,bx( nlf, 1_${ik}$ ), & ldbx, perm( nlf, lvl ),givptr( j ), givcol( nlf, lvl2 ), ldgcol,givnum( nlf, & lvl2 ), ldu, poles( nlf, lvl2 ),difl( nlf, lvl ), difr( nlf, lvl2 ),z( nlf, lvl )& , k( j ), c( j ), s( j ), work,info ) end do end do loop_70 ! the nodes on the bottom level of the tree were solved ! by stdlib${ii}$_slasdq. the corresponding right singular vector ! matrices are in explicit form. apply them back. ndb1 = ( nd+1 ) / 2_${ik}$ do i = ndb1, nd i1 = i - 1_${ik}$ ic = iwork( inode+i1 ) nl = iwork( ndiml+i1