correction of a dense symmetric positive definite matrix a+e in the
factored form a+e=l*d*trans(l) obtained by the subroutine mxdpgf.
the correction is defined as a+e:=a+e+alf*x*trans(x) where alf is a
given scaling factor and x is a given vector.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n |
order of the matrix a. |
||
| real(kind=wp), | intent(inout) | :: | a(*) |
|
||
| real(kind=wp), | intent(in) | :: | alf |
scaling factor in the correction term. |
||
| real(kind=wp), | intent(in) | :: | x(*) |
vector in the correction term. |
||
| real(kind=wp), | intent(out) | :: | y(*) |
auxiliary vector. |
pure subroutine mxdpgu(n,a,alf,x,y) integer,intent(in) :: n !! order of the matrix a. real(wp),intent(in) :: alf !! scaling factor in the correction term. real(wp),intent(inout) :: a(*) !! `a(n*(n+1)/2)` factorization `a+e=l*d*trans(l)` !! obtained by the subroutine [[mxdpgf]]. real(wp),intent(in) :: x(*) !! vector in the correction term. real(wp),intent(out) :: y(*) !! auxiliary vector. real(wp) :: alfr real(wp) :: b , d , p , r , t , to integer :: i , ii , ij , j real(wp), parameter :: zero = 0.0_wp real(wp), parameter :: one = 1.0_wp real(wp), parameter :: four = 4.0_wp real(wp), parameter :: con = 1.0e-8_wp if ( alf>=zero ) then ! forward correction in case when the scaling factor is nonnegative alfr = sqrt(alf) call mxvscl(n,alfr,x,y) to = one ii = 0 do i = 1 , n ii = ii + i d = a(ii) p = y(i) t = to + p*p/d r = to/t a(ii) = d/r b = p/(d*t) if ( a(ii)<=four*d ) then ! an easy formula for limited diagonal element ij = ii do j = i + 1 , n ij = ij + j - 1 d = a(ij) y(j) = y(j) - p*d a(ij) = d + b*y(j) end do else ! a more complicate but numerically stable formula for unlimited ! diagonal element ij = ii do j = i + 1 , n ij = ij + j - 1 d = a(ij) a(ij) = r*d + b*y(j) y(j) = y(j) - p*d end do endif to = t end do else ! backward correction in case when the scaling factor is negative alfr = sqrt(-alf) call mxvscl(n,alfr,x,y) to = one ij = 0 do i = 1 , n d = y(i) do j = 1 , i - 1 ij = ij + 1 d = d - a(ij)*y(j) end do y(i) = d ij = ij + 1 to = to - d*d/a(ij) end do if ( to<=zero ) to = con ii = n*(n+1)/2 do i = n , 1 , -1 d = a(ii) p = y(i) t = to + p*p/d a(ii) = d*to/t b = -p/(d*to) to = t ij = ii do j = i + 1 , n ij = ij + j - 1 d = a(ij) a(ij) = d + b*y(j) y(j) = y(j) + p*d end do ii = ii - i end do endif end subroutine mxdpgu