solve the real band system a*x=b
or trans(a)*x=b
using
the factors computed by dgbco or dgbfa.
to compute inverse(a) * c
where c
is a matrix
with p
columns:
call dgbco(abd,lda,n,ml,mu,ipvt,rcond,z)
if (rcond is too small) go to ...
do j = 1, p
call dgbsl(abd,lda,n,ml,mu,ipvt,c(1,j),0)
end do
a division by zero will occur if the input factor contains a
zero on the diagonal. technically this indicates singularity
but it is often caused by improper arguments or improper
setting of lda
. it will not occur if the subroutines are
called correctly and if dgbco has set rcond > 0.0
or dgbfa has set info == 0
.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=wp), | intent(in) | :: | abd(lda,*) | |||
integer, | intent(in) | :: | lda |
the leading dimension of the array |
||
integer, | intent(in) | :: | n |
the order of the original matrix. |
||
integer, | intent(in) | :: | ml |
number of diagonals below the main diagonal. |
||
integer, | intent(in) | :: | mu |
number of diagonals above the main diagonal. |
||
integer, | intent(in) | :: | ipvt(*) | |||
real(kind=wp), | intent(inout) | :: | b(*) |
|
||
integer, | intent(in) | :: | job |
|
subroutine dgbsl(abd,lda,n,ml,mu,ipvt,b,job) integer,intent(in) :: lda !! the leading dimension of the array `abd`. integer,intent(in) :: n !! the order of the original matrix. integer,intent(in) :: ml !! number of diagonals below the main diagonal. integer,intent(in) :: mu !! number of diagonals above the main diagonal. integer,intent(in) :: ipvt(*) !! the pivot vector from [[dgbco]] or [[dgbfa]]. integer,intent(in) :: job !! * 0 to solve `a*x = b` , !! * nonzero to solve `trans(a)*x = b` , where !! `trans(a)` is the transpose. real(wp),intent(in) :: abd(lda,*) !! the output from [[dgbco]] or [[dgbfa]]. real(wp),intent(inout) :: b(*) !! * **input:** the right hand side vector. !! * **output:** the solution vector `x`. real(wp) :: t integer :: k , kb , l , la , lb , lm , m , nm1 #ifdef HAS_BLAS ! user is linking against an external BLAS library double precision,external :: ddot #endif m = mu + ml + 1 nm1 = n - 1 if ( job/=0 ) then ! job = nonzero, solve trans(a) * x = b ! first solve trans(u)*y = b do k = 1 , n lm = min(k,m) - 1 la = m - lm lb = k - lm t = ddot(lm,abd(la,k),1,b(lb),1) b(k) = (b(k)-t)/abd(m,k) enddo ! now solve trans(l)*x = y if ( ml/=0 ) then if ( nm1>=1 ) then do kb = 1 , nm1 k = n - kb lm = min(ml,n-k) b(k) = b(k) + ddot(lm,abd(m+1,k),1,b(k+1),1) l = ipvt(k) if ( l/=k ) then t = b(l) b(l) = b(k) b(k) = t endif enddo endif endif else ! job = 0 , solve a * x = b ! first solve l*y = b if ( ml/=0 ) then if ( nm1>=1 ) then do k = 1 , nm1 lm = min(ml,n-k) l = ipvt(k) t = b(l) if ( l/=k ) then b(l) = b(k) b(k) = t endif call daxpy(lm,t,abd(m+1,k),1,b(k+1),1) enddo endif endif ! now solve u*x = y do kb = 1 , n k = n + 1 - kb b(k) = b(k)/abd(m,k) lm = min(k,m) - 1 la = m - lm lb = k - lm t = -b(k) call daxpy(lm,t,abd(la,k),1,b(lb),1) enddo endif end subroutine dgbsl