r1updt Subroutine

public subroutine r1updt(m, n, s, ls, u, v, w, sing)

given an m by n lower trapezoidal matrix s, an m-vector u, and an n-vector v, the problem is to determine an orthogonal matrix q such that

          t
  (s + u*v )*q

is again lower trapezoidal.

this subroutine determines q as the product of 2*(n - 1) transformations

  gv(n-1)*...*gv(1)*gw(1)*...*gw(n-1)

where gv(i), gw(i) are givens rotations in the (i,n) plane which eliminate elements in the i-th and n-th planes, respectively. q itself is not accumulated, rather the information to recover the gv, gw rotations is returned.

the subroutine statement is

subroutine r1updt(m,n,s,ls,u,v,w,sing)

where

m is a positive integer input variable set to the number of rows of s.

n is a positive integer input variable set to the number of columns of s. n must not exceed m.

s is an array of length ls. on input s must contain the lower trapezoidal matrix s stored by columns. on output s contains the lower trapezoidal matrix produced as described above.

ls is a positive integer input variable not less than (n(2m-n+1))/2.

u is an input array of length m which must contain the vector u.

v is an array of length n. on input v must contain the vector v. on output v(i) contains the information necessary to recover the givens rotation gv(i) described above.

w is an output array of length m. w(i) contains information necessary to recover the givens rotation gw(i) described above.

sing is a logical output variable. sing is set true if any of the diagonal elements of the output s are zero. otherwise sing is set false.

Arguments

Type IntentOptional Attributes Name
integer :: m
integer :: n
real(kind=wp) :: s(ls)
integer :: ls
real(kind=wp) :: u(m)
real(kind=wp) :: v(n)
real(kind=wp) :: w(m)
logical :: sing

Calls

proc~~r1updt~~CallsGraph proc~r1updt minpack_module::r1updt proc~dpmpar minpack_module::dpmpar proc~r1updt->proc~dpmpar

Called by

proc~~r1updt~~CalledByGraph proc~r1updt minpack_module::r1updt proc~hybrd minpack_module::hybrd proc~hybrd->proc~r1updt proc~hybrj minpack_module::hybrj proc~hybrj->proc~r1updt proc~hybrd1 minpack_module::hybrd1 proc~hybrd1->proc~hybrd proc~hybrj1 minpack_module::hybrj1 proc~hybrj1->proc~hybrj proc~halo_to_rv_diffcorr halo_orbit_module::halo_to_rv_diffcorr proc~halo_to_rv_diffcorr->proc~hybrd1

Source Code

    subroutine r1updt(m,n,s,ls,u,v,w,sing)

    implicit none

    integer m , n , ls
    logical sing
    real(wp) s(ls) , u(m) , v(n) , w(m)

      integer i , j , jj , l , nmj , nm1
      real(wp) cos , cotan , giant , sin ,     &
                     & tan , tau , temp

      real(wp),parameter :: p5  = 5.0e-1_wp
      real(wp),parameter :: p25 = 2.5e-1_wp
!
!     giant is the largest magnitude.
!
      giant = dpmpar(3)
!
!     initialize the diagonal element pointer.
!
      jj = (n*(2*m-n+1))/2 - (m-n)
!
!     move the nontrivial part of the last column of s into w.
!
      l = jj
      do i = n , m
         w(i) = s(l)
         l = l + 1
      enddo
!
!     rotate the vector v into a multiple of the n-th unit vector
!     in such a way that a spike is introduced into w.
!
      nm1 = n - 1
      if ( nm1>=1 ) then
         do nmj = 1 , nm1
            j = n - nmj
            jj = jj - (m-j+1)
            w(j) = zero
            if ( v(j)/=zero ) then
!
!        determine a givens rotation which eliminates the
!        j-th element of v.
!
               if ( abs(v(n))>=abs(v(j)) ) then
                  tan = v(j)/v(n)
                  cos = p5/sqrt(p25+p25*tan**2)
                  sin = cos*tan
                  tau = sin
               else
                  cotan = v(n)/v(j)
                  sin = p5/sqrt(p25+p25*cotan**2)
                  cos = sin*cotan
                  tau = one
                  if ( abs(cos)*giant>one ) tau = one/cos
               endif
!
!        apply the transformation to v and store the information
!        necessary to recover the givens rotation.
!
               v(n) = sin*v(j) + cos*v(n)
               v(j) = tau
!
!        apply the transformation to s and extend the spike in w.
!
               l = jj
               do i = j , m
                  temp = cos*s(l) - sin*w(i)
                  w(i) = sin*s(l) + cos*w(i)
                  s(l) = temp
                  l = l + 1
               enddo
            endif
         enddo
      endif
!
!     add the spike from the rank 1 update to w.
!
      do i = 1 , m
         w(i) = w(i) + v(n)*u(i)
      enddo
!
!     eliminate the spike.
!
      sing = .false.
      if ( nm1>=1 ) then
         do j = 1 , nm1
            if ( w(j)/=zero ) then
!
!        determine a givens rotation which eliminates the
!        j-th element of the spike.
!
               if ( abs(s(jj))>=abs(w(j)) ) then
                  tan = w(j)/s(jj)
                  cos = p5/sqrt(p25+p25*tan**2)
                  sin = cos*tan
                  tau = sin
               else
                  cotan = s(jj)/w(j)
                  sin = p5/sqrt(p25+p25*cotan**2)
                  cos = sin*cotan
                  tau = one
                  if ( abs(cos)*giant>one ) tau = one/cos
               endif
!
!        apply the transformation to s and reduce the spike in w.
!
               l = jj
               do i = j , m
                  temp = cos*s(l) + sin*w(i)
                  w(i) = -sin*s(l) + cos*w(i)
                  s(l) = temp
                  l = l + 1
               enddo
!
!        store the information necessary to recover the
!        givens rotation.
!
               w(j) = tau
            endif
!
!        test for zero diagonal elements in the output s.
!
            if ( s(jj)==zero ) sing = .true.
            jj = jj + (m-j+1)
         enddo
      endif
!
!     move w back into the last column of the output s.
!
      l = jj
      do i = n , m
         s(l) = w(i)
         l = l + 1
      enddo
      if ( s(jj)==zero ) sing = .true.

      end subroutine r1updt