dwnlit Subroutine

private subroutine dwnlit(w, mdw, m, n, l, ipivot, itype, h, scale, rnorm, idope, dope, done)

This is a companion subprogram to DWNNLS. The documentation for DWNNLS has complete usage instructions.

Note: The M by (N+1) matrix W( , ) contains the rt. hand side B as the (N+1)st col.

Triangularize L1 by L1 subsystem, where L1=MIN(M,L), with col interchanges.

Revision history

  • 790701 DATE WRITTEN. Hanson, R. J., (SNLA), Haskell, K. H., (SNLA)
  • 890531 Changed all specific intrinsics to generic. (WRB)
  • 890618 Completely restructured and revised. (WRB & RWC)
  • 890620 Revised to make WNLT1, WNLT2, and WNLT3 subroutines. (RWC)
  • 891214 Prologue converted to Version 4.0 format. (BAB)
  • 900328 Added TYPE section. (WRB)
  • 900604 DP version created from SP version. . (RWC)

Arguments

Type IntentOptional Attributes Name
real(kind=wp) :: w(mdw,*)
integer :: mdw
integer :: m
integer :: n
integer :: l
integer :: ipivot(*)
integer :: itype(*)
real(kind=wp) :: h(*)
real(kind=wp) :: scale(*)
real(kind=wp) :: rnorm
integer :: idope(*)
real(kind=wp) :: dope(*)
logical :: done

Calls

proc~~dwnlit~~CallsGraph proc~dwnlit bspline_defc_module::dwnlit proc~dcopy bspline_blas_module::dcopy proc~dwnlit->proc~dcopy proc~dh12 bspline_defc_module::dh12 proc~dwnlit->proc~dh12 proc~drotm bspline_blas_module::drotm proc~dwnlit->proc~drotm proc~drotmg bspline_blas_module::drotmg proc~dwnlit->proc~drotmg proc~dscal bspline_blas_module::dscal proc~dwnlit->proc~dscal proc~dswap bspline_blas_module::dswap proc~dwnlit->proc~dswap proc~dwnlt1 bspline_defc_module::dwnlt1 proc~dwnlit->proc~dwnlt1 proc~dwnlt2 bspline_defc_module::dwnlt2 proc~dwnlit->proc~dwnlt2 proc~dwnlt3 bspline_defc_module::dwnlt3 proc~dwnlit->proc~dwnlt3 proc~idamax bspline_blas_module::idamax proc~dwnlit->proc~idamax proc~dh12->proc~dswap proc~daxpy bspline_blas_module::daxpy proc~dh12->proc~daxpy proc~ddot bspline_blas_module::ddot proc~dh12->proc~ddot proc~dwnlt1->proc~idamax proc~dwnlt3->proc~dswap

Called by

proc~~dwnlit~~CalledByGraph proc~dwnlit bspline_defc_module::dwnlit proc~dwnlsm bspline_defc_module::dwnlsm proc~dwnlsm->proc~dwnlit proc~dwnnls bspline_defc_module::dwnnls proc~dwnnls->proc~dwnlsm proc~dlpdp bspline_defc_module::dlpdp proc~dlpdp->proc~dwnnls proc~dlsi bspline_defc_module::dlsi proc~dlsi->proc~dlpdp proc~dlsei bspline_defc_module::dlsei proc~dlsei->proc~dlsi proc~dfcmn bspline_defc_module::dfcmn proc~dfcmn->proc~dlsei proc~dfc bspline_defc_module::dfc proc~dfc->proc~dfcmn

Source Code

   subroutine dwnlit (w, mdw, m, n, l, ipivot, itype, h, scale, &
                      rnorm, idope, dope, done)

   integer :: idope(*), ipivot(*), itype(*), l, m, mdw, n
   real(wp) :: dope(*), h(*), rnorm, scale(*), w(mdw,*)
   logical :: done

   real(wp) :: alsq, amax, eanorm, factor, hbar, rn, sparam(5), &
               t, tau
   integer :: i, i1, imax, ir, j, j1, jj, jp, krank, l1, lb, lend, me, &
              mend, niv, nsoln
   logical :: indep, recalc

   me     = idope(1)
   nsoln  = idope(2)
   l1     = idope(3)
   alsq   = dope(1)
   eanorm = dope(2)
   tau    = dope(3)
   lb     = min(m-1,l)
   recalc = .true.
   rnorm  = 0.0_wp
   krank  = 0

   ! We set FACTOR=1.0 so that the heavy weight ALAMDA will be
   ! included in the test for column independence.
   factor = 1.0_wp
   lend = l

   main : block

      do i=1,lb

         ! Set IR to point to the I-th row.
         ir = i
         mend = m
         call dwnlt1 (i, lend, m, ir, mdw, recalc, imax, hbar, h, scale, w)

         ! Update column SS and find pivot column.
         call dwnlt3 (i, imax, m, mdw, ipivot, h, w)

         do
            ! Perform column interchange.
            ! Test independence of incoming column.
            if (dwnlt2(me, mend, ir, factor, tau, scale, w(1,i))) then

               ! Eliminate I-th column below diagonal using modified Givens
               ! transformations applied to (A B).
               !
               ! When operating near the ME line, use the largest element
               ! above it as the pivot.
               do j=m,i+1,-1
                  jp = j-1
                  if (j==me+1) then
                     imax = me
                     amax = scale(me)*w(me,i)**2
                     do jp=j-1,i,-1
                        t = scale(jp)*w(jp,i)**2
                        if (t>amax) then
                           imax = jp
                           amax = t
                        endif
                     end do
                     jp = imax
                  endif
                  if (w(j,i)/=0.0_wp) then
                     call drotmg (scale(jp), scale(j), w(jp,i), w(j,i), &
                                 sparam)
                     w(j,i) = 0.0_wp
                     call drotm (n+1-i, w(jp,i+1), mdw, w(j,i+1), mdw, &
                                 sparam)
                  endif
               end do
               exit
            else if (lend>i) then
               ! Column I is dependent.  Swap with column LEND.
               ! Perform column interchange,
               ! and find column in remaining set with largest SS.
               call dwnlt3 (i, lend, m, mdw, ipivot, h, w)
               lend = lend - 1
               imax = idamax(lend-i+1, h(i), 1) + i - 1
               hbar = h(imax)
            else
               krank = i - 1
               exit main
            endif
         end do

      end do
      krank = l1

   end block main

   if (krank<me) then
      factor = alsq
      do i=krank+1,me
         call dcopy (l, [0.0_wp], 0, w(i,1), mdw)
      end do

      ! Determine the rank of the remaining equality constraint
      ! equations by eliminating within the block of constrained
      ! variables.  Remove any redundant constraints.

      recalc = .true.
      lb = min(l+me-krank, n)
      do i=l+1,lb
         ir = krank + i - l
         lend = n
         mend = me
         call dwnlt1 (i, lend, me, ir, mdw, recalc, imax, hbar, h, &
                      scale, w)

         ! Update col ss and find pivot col
         call dwnlt3 (i, imax, m, mdw, ipivot, h, w)

         ! Perform column interchange
         ! Eliminate elements in the I-th col.
         do j=me,ir+1,-1
            if (w(j,i)/=0.0_wp) then
              call drotmg (scale(j-1), scale(j), w(j-1,i), w(j,i), &
                           sparam)
               w(j,i) = 0.0_wp
               call drotm (n+1-i, w(j-1,i+1), mdw,w(j,i+1), mdw, &
                           sparam)
            endif
         end do

         ! I=column being eliminated.
         ! Test independence of incoming column.
         ! Remove any redundant or dependent equality constraints.
         if (.not.dwnlt2(me, mend, ir, factor,tau,scale,w(1,i))) then
            jj = ir
            do ir=jj,me
               call dcopy (n, [0.0_wp], 0, w(ir,1), mdw)
               rnorm = rnorm + (scale(ir)*w(ir,n+1)/alsq)*w(ir,n+1)
               w(ir,n+1) = 0.0_wp
               scale(ir) = 1.0_wp
               ! Reclassify the zeroed row as a least squares equation.
               itype(ir) = 1
            end do
            ! Reduce ME to reflect any discovered dependent equality
            ! constraints.
            me = jj - 1
            exit
         endif
      end do
   endif

   ! Try to determine the variables KRANK+1 through L1 from the
   ! least squares equations.  Continue the triangularization with
   ! pivot element W(ME+1,I).
   if (krank<l1) then
      recalc = .true.

      ! Set FACTOR=ALSQ to remove effect of heavy weight from
      ! test for column independence.
      factor = alsq
      do i=krank+1,l1

         ! Set IR to point to the ME+1-st row.
         ir = me+1
         lend = l
         mend = m
         call dwnlt1 (i, l, m, ir, mdw, recalc, imax, hbar, h, scale, w)

         ! Update column SS and find pivot column.
         call dwnlt3 (i, imax, m, mdw, ipivot, h, w)

         ! Perform column interchange.
         ! Eliminate I-th column below the IR-th element.
         do j=m,ir+1,-1
            if (w(j,i)/=0.0_wp) then
               call drotmg (scale(j-1), scale(j), w(j-1,i), w(j,i), sparam)
               w(j,i) = 0.0_wp
               call drotm (n+1-i, w(j-1,i+1),  mdw, w(j,i+1), mdw, sparam)
            endif
         end do

         ! Test if new pivot element is near zero.
         ! If so, the column is dependent.
         ! Then check row norm test to be classified as independent.
         t = scale(ir)*w(ir,i)**2
         indep = t > (tau*eanorm)**2
         if (indep) then
            rn = 0.0_wp
            do i1=ir,m
               do j1=i+1,n
                  rn = max(rn, scale(i1)*w(i1,j1)**2)
               end do
            end do
            indep = t > rn*tau**2
         endif

         ! If independent, swap the IR-th and KRANK+1-th rows to
         ! maintain the triangular form.  Update the rank indicator
         ! KRANK and the equality constraint pointer ME.
         if (.not.indep) exit
         call dswap(n+1, w(krank+1,1), mdw, w(ir,1), mdw)
         call dswap(1, scale(krank+1), 1, scale(ir), 1)

         ! Reclassify the least square equation as an equality
         ! constraint and rescale it.
         itype(ir) = 0
         t = sqrt(scale(krank+1))
         call dscal(n+1, t, w(krank+1,1), mdw)
         scale(krank+1) = alsq
         me = me+1
         krank = krank+1
      end do
   endif

   ! If pseudorank is less than L, apply Householder transformation.
   ! from right.
   if (krank<l) then
      do j=krank,1,-1
         call dh12 (1, j, krank+1, l, w(j,1), mdw, h(j), w, mdw, 1, &
                   j-1)
      end do
   endif

   niv = krank + nsoln - l
   if (l==n) done = .true.

   ! End of initial triangularization.
   idope(1) = me
   idope(2) = krank
   idope(3) = niv

   end subroutine dwnlit