Construction and/or application of a single
Householder transformation. Q = I + U*(U**T)/B
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | Mode |
1 or 2 to select algorithm H1 or H2 . |
||
integer, | intent(in) | :: | Lpivot |
the index of the pivot element. |
||
integer, | intent(in) | :: | l1 |
If |
||
integer, | intent(in) | :: | m |
see |
||
real(kind=wp), | intent(inout) | :: | u(Iue,*) |
On entry to H1 |
||
integer, | intent(in) | :: | Iue |
the storage increment between elements of |
||
real(kind=wp), | intent(inout) | :: | Up |
see |
||
real(kind=wp), | intent(inout) | :: | c(*) |
On entry to H1 or H2 |
||
integer, | intent(in) | :: | Ice |
Storage increment between elements of vectors in |
||
integer, | intent(in) | :: | Icv |
Storage increment between vectors in |
||
integer, | intent(in) | :: | Ncv |
Number of vectors in |
subroutine dh12(Mode, Lpivot, l1, m, u, Iue, Up, c, Ice, Icv, Ncv) integer,intent(in) :: Mode !! 1 or 2 to select algorithm H1 or H2 . integer,intent(in) :: Lpivot !! the index of the pivot element. integer,intent(in) :: l1 !! If `L1 <= M` the transformation will be constructed to !! zero elements indexed from `L1` through `M`. If `L1 > M` !! the subroutine does an identity transformation. integer,intent(in) :: m !! see `l1` integer,intent(in) :: Iue !! the storage increment between elements of `U`. real(wp),intent(inout) :: u(Iue, *) !! On entry to H1 `U()` contains the pivot vector. !! On exit from H1 `U()` and `UP` !! contain quantities defining the vector `U` of the !! Householder transformation. On entry to H2 `U()` !! and `UP` should contain quantities previously computed !! by H1. These will not be modified by H2. real(wp),intent(inout) :: Up !! see `u` real(wp),intent(inout) :: c(*) !! On entry to H1 or H2 `C()` contains a matrix which will be !! regarded as a set of vectors to which the Householder !! transformation is to be applied. On exit `C()` contains the !! set of transformed vectors. integer,intent(in) :: Ice !! Storage increment between elements of vectors in `C()`. integer,intent(in) :: Icv !! Storage increment between vectors in `C()`. integer,intent(in) :: Ncv !! Number of vectors in `C()` to be transformed. If `NCV <= 0` !! no operations will be done on `C()`. integer :: i, i2, i3, i4, incr, j, kl1, & kl2, klp, l1m1, mml1p2 real(wp) :: b, cl, clinv, ul1m1, sm real(wp), parameter :: one = 1.0_wp if (0 < Lpivot .and. Lpivot < l1 .and. l1 <= m) then cl = abs(u(1, Lpivot)) if (Mode /= 2) then ! ****** CONSTRUCT THE TRANSFORMATION. ****** do j = l1, m cl = max(abs(u(1, j)), cl) end do if (cl <= 0.0_wp) return clinv = one/cl sm = (u(1, Lpivot)*clinv)**2 do j = l1, m sm = sm + (u(1, j)*clinv)**2 end do cl = cl*sqrt(sm) if (u(1, Lpivot) > 0.0_wp) cl = -cl Up = u(1, Lpivot) - cl u(1, Lpivot) = cl ! ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C. ****** elseif (cl <= 0.0_wp) then return end if if (Ncv > 0) then b = Up*u(1, Lpivot) ! B MUST BE NONPOSITIVE HERE. IF B = 0., RETURN. if (b < 0.0_wp) then b = one/b mml1p2 = m - l1 + 2 if (mml1p2 <= 20) then i2 = 1 - Icv + Ice*(Lpivot - 1) incr = Ice*(l1 - Lpivot) do j = 1, Ncv i2 = i2 + Icv i3 = i2 + incr i4 = i3 sm = c(i2)*Up do i = l1, m sm = sm + c(i3)*u(1, i) i3 = i3 + Ice end do if (sm /= 0.0_wp) then sm = sm*b c(i2) = c(i2) + sm*Up do i = l1, m c(i4) = c(i4) + sm*u(1, i) i4 = i4 + Ice end do end if end do else l1m1 = l1 - 1 kl1 = 1 + (l1m1 - 1)*Ice kl2 = kl1 klp = 1 + (Lpivot - 1)*Ice ul1m1 = u(1, l1m1) u(1, l1m1) = Up if (Lpivot /= l1m1) call dswap(Ncv, c(kl1), Icv, c(klp), Icv) do j = 1, Ncv sm = ddot(mml1p2, u(1, l1m1), Iue, c(kl1), Ice) sm = sm*b call daxpy(mml1p2, sm, u(1, l1m1), Iue, c(kl1), Ice) kl1 = kl1 + Icv end do u(1, l1m1) = ul1m1 if (Lpivot /= l1m1) then kl1 = kl2 call dswap(Ncv, c(kl1), Icv, c(klp), Icv) end if end if end if end if end if end subroutine dh12