      subroutine ntrust(n,x,f,fjac,diag,delta)
c     **********
c
c     Subroutine ntrust
c
c     This subroutine solves the system of equations f(x) = 0
c     by a trust region verion of a truncated Newton method.
c
c     **********

c     Check the input parameters for errors.

c     Evaluate the function at the starting point
c     and calculate its norm.

      call fcn(n,x,f,fjac,ldfjac,1)
      nfev = 1

      fnorm = dnrm2(n,f)

c     Initialize trust region parameter delta

      delta = p1*fnorm

c     Beginning of the outer loop.

      do until (info != 0)

c        Calculate the Jacobian matrix.

         call fcn(n,x,f,fjac,ldfjac,2)

c        Compute a scaling matrix.

         do j = 1, n
            diag(j) = dnrm2(n,fjac(1,j))
         end

c        Beginning of the inner loop.

         do until (actred > p0001*prered) 

c           Compute the step p

            call dogleg(n,f,fjac,diag,delta)

c           Store the direction p and x + p. Calculate the norm of p.

            xtrial = x + p
            pnorm = dnrm2(n,p)

c           Evaluate the function at x + p and calculate its norm.

            call fcn(n,xtrial,ftrial,fjac,ldfjac,1)
            nfev += 1
            fnormt = dnrm2(n,ftrial)

c           Compute the scaled actual reduction.

            if (p1*fnorm1 <= fnorm) then
               actred = one - (fnorm1/fnorm)**2
            else
               actred = -one
            end if

c           Compute the scaled predicted reduction

            flinear = f + fjac*p
            prered = 1 - (dnrm2(n,flinear)/fnorm)**2

c           Compute the scaled directional derivative.

            dirder = (ddot(n,f,flinear)/fnorm)/fnorm - 1

c           Update the step bound.

            if (actred <= p25*prered) then
               if (actred >= zero) then
                  decrease = p5
               else
                  decrease = p5*dirder/(dirder + p5*actred)
                  end if
               if (p1*fnorm1 >= fnorm || decrease < p1) decrease = p1
               delta = decrease*min(delta,pnorm/p1)
            else if (actred >= p75*prered) then
               delta = pnorm/p5
               end if

c           Test for successful iteration.

            if (actred >= p0001*prered) then

c              Successful iteration. Update x, f, and their norms.

               x = xtrial
               f = ftrial
               xnorm = dnrm2(n,x)
               fnorm = fnormt
               end if

c           Tests for convergence.

            if (abs(actred) <= ftol && prered <= ftol
     *          && p5*actred <= prered) info = 1
            if (delta <= xtol*xnorm) info = 2
            if (abs(actred) <= ftol && prered <= ftol
     *          && p5*actred <= prered && info == 2) info = 3
            if (info != 0) go to termination

c           Tests for termination and stringent tolerances.

            if (nfev >= maxfev) info = 5
            if (abs(actred) <= epsmch && prered <= epsmch
     *          && p5*ratio <= one) info = 6
            if (delta <= epsmch*xnorm) info = 7
            if (info != 0) go to termination

c           End of the inner loop. Repeat if iteration unsuccessful.

c        End of the outer loop.

c     Termination, either normal or user imposed.

      return

c     Last card of subroutine lmder-gropp.

      end
