      SUBROUTINE DRMNG(D, FX, G, IV, LIV, LV, N, V, X)
C
C  ***  CARRY OUT  DMNG (UNCONSTRAINED MINIMIZATION) ITERATIONS, USING
C  ***  DOUBLE-DOGLEG/BFGS STEPS.
C
C  ***  PARAMETER DECLARATIONS  ***
C
      INTEGER LIV, LV, N
      INTEGER IV(LIV)
      DOUBLE PRECISION D(N), FX, G(N), V(LV), X(N)
C
C--------------------------  PARAMETER USAGE  --------------------------
C
C D.... SCALE VECTOR.
C FX... FUNCTION VALUE.
C G.... GRADIENT VECTOR.
C IV... INTEGER VALUE ARRAY.
C LIV.. LENGTH OF IV (AT LEAST 60).
C LV... LENGTH OF V (AT LEAST 71 + N*(N+13)/2).
C N.... NUMBER OF VARIABLES (COMPONENTS IN X AND G).
C V.... FLOATING-POINT VALUE ARRAY.
C X.... VECTOR OF PARAMETERS TO BE OPTIMIZED.
C
C  ***  DISCUSSION  ***
C
C        PARAMETERS IV, N, V, AND X ARE THE SAME AS THE CORRESPONDING
C     ONES TO  DMNG (WHICH SEE), EXCEPT THAT V CAN BE SHORTER (SINCE
C     THE PART OF V THAT  DMNG USES FOR STORING G IS NOT NEEDED).
C     MOREOVER, COMPARED WITH  DMNG, IV(1) MAY HAVE THE TWO ADDITIONAL
C     OUTPUT VALUES 1 AND 2, WHICH ARE EXPLAINED BELOW, AS IS THE USE
C     OF IV(TOOBIG) AND IV(NFGCAL).  THE VALUE IV(G), WHICH IS AN
C     OUTPUT VALUE FROM  DMNG (AND  DMNF), IS NOT REFERENCED BY
C     DRMNG OR THE SUBROUTINES IT CALLS.
C        FX AND G NEED NOT HAVE BEEN INITIALIZED WHEN DRMNG IS CALLED
C     WITH IV(1) = 12, 13, OR 14.
C
C IV(1) = 1 MEANS THE CALLER SHOULD SET FX TO F(X), THE FUNCTION VALUE
C             AT X, AND CALL DRMNG AGAIN, HAVING CHANGED NONE OF THE
C             OTHER PARAMETERS.  AN EXCEPTION OCCURS IF F(X) CANNOT BE
C             (E.G. IF OVERFLOW WOULD OCCUR), WHICH MAY HAPPEN BECAUSE
C             OF AN OVERSIZED STEP.  IN THIS CASE THE CALLER SHOULD SET
C             IV(TOOBIG) = IV(2) TO 1, WHICH WILL CAUSE DRMNG TO IG-
C             NORE FX AND TRY A SMALLER STEP.  THE PARAMETER NF THAT
C              DMNG PASSES TO CALCF (FOR POSSIBLE _USE_ BY CALCG) IS A
C             COPY OF IV(NFCALL) = IV(6).
C IV(1) = 2 MEANS THE CALLER SHOULD SET G TO G(X), THE GRADIENT VECTOR
C             OF F AT X, AND CALL DRMNG AGAIN, HAVING CHANGED NONE OF
C             THE OTHER PARAMETERS EXCEPT POSSIBLY THE SCALE VECTOR D
C             WHEN IV(DTYPE) = 0.  THE PARAMETER NF THAT  DMNG PASSES
C             TO CALCG IS IV(NFGCAL) = IV(7).  IF G(X) CANNOT BE
C             EVALUATED, THEN THE CALLER MAY SET IV(TOOBIG) TO 0, IN
C             WHICH CASE DRMNG WILL RETURN WITH IV(1) = 65.
C.
C  ***  GENERAL  ***
C
C     CODED BY DAVID M. GAY (DECEMBER 1979).  REVISED SEPT. 1982.
C     THIS SUBROUTINE WAS WRITTEN IN CONNECTION WITH RESEARCH SUPPORTED
C     IN PART BY THE NATIONAL SCIENCE FOUNDATION UNDER GRANTS
C     MCS-7600324 AND MCS-7906671.
C
C        (SEE  DMNG FOR REFERENCES.)
C
C+++++++++++++++++++++++++++  DECLARATIONS  ++++++++++++++++++++++++++++
C
C  ***  LOCAL VARIABLES  ***
C
      INTEGER DG1, DUMMY, G01, I, K, L, LSTGST, NWTST1, RSTRST, STEP1,
     1        TEMP1, W, X01, Z
      DOUBLE PRECISION T
C
C     ***  CONSTANTS  ***
C
      DOUBLE PRECISION HALF, NEGONE, ONE, ONEP2, ZERO
C
C  ***  NO INTRINSIC FUNCTIONS  ***
C
C  ***  EXTERNAL FUNCTIONS AND SUBROUTINES  ***
C
      LOGICAL STOPX
      DOUBLE PRECISION DD7TPR, DRLDST, DV2NRM
      EXTERNAL DA7SST,DD7DOG,DIVSET, DD7TPR,DITSUM, DL7ITV, DL7IVM,
     1         DL7TVM, DL7UPD,DL7VML,DPARCK, DRLDST, STOPX,DV2AXY,
     2        DV7CPY, DV7SCP, DV7VMP, DV2NRM, DW7ZBF
C
C DA7SST.... ASSESSES CANDIDATE STEP.
C DD7DOG.... COMPUTES DOUBLE-DOGLEG (CANDIDATE) STEP.
C DIVSET.... SUPPLIES DEFAULT IV AND V INPUT COMPONENTS.
C DD7TPR... RETURNS INNER PRODUCT OF TWO VECTORS.
C DITSUM.... PRINTS ITERATION SUMMARY AND INFO ON INITIAL AND FINAL X.
C DL7ITV... MULTIPLIES INVERSE TRANSPOSE OF LOWER TRIANGLE TIMES VECTOR.
C DL7IVM... MULTIPLIES INVERSE OF LOWER TRIANGLE TIMES VECTOR.
C DL7TVM... MULTIPLIES TRANSPOSE OF LOWER TRIANGLE TIMES VECTOR.
C LUPDT.... UPDATES CHOLESKY FACTOR OF HESSIAN APPROXIMATION.
C DL7VML.... MULTIPLIES LOWER TRIANGLE TIMES VECTOR.
C DPARCK.... CHECKS VALIDITY OF INPUT IV AND V VALUES.
C DRLDST... COMPUTES V(RELDX) = RELATIVE STEP SIZE.
C STOPX.... RETURNS .TRUE. IF THE BREAK KEY HAS BEEN PRESSED.
C DV2AXY.... COMPUTES SCALAR TIMES ONE VECTOR PLUS ANOTHER.
C DV7CPY.... COPIES ONE VECTOR TO ANOTHER.
C DV7SCP... SETS ALL ELEMENTS OF A VECTOR TO A SCALAR.
C DV7VMP... MULTIPLIES VECTOR BY VECTOR RAISED TO POWER (COMPONENTWISE).
C DV2NRM... RETURNS THE 2-NORM OF A VECTOR.
C DW7ZBF... COMPUTES W AND Z FOR DL7UPD CORRESPONDING TO BFGS UPDATE.
C
C  ***  SUBSCRIPTS FOR IV AND V  ***
C
      INTEGER CNVCOD, DG, DGNORM, DINIT, DSTNRM, DST0, F, F0, FDIF,
     1        GTHG, GTSTEP, G0, INCFAC, INITH, IRC, KAGQT, LMAT, LMAX0,
     2        LMAXS, MODE, MODEL, MXFCAL, MXITER, NEXTV, NFCALL, NFGCAL,
     3        NGCALL, NITER, NREDUC, NWTSTP, PREDUC, RADFAC, RADINC,
     4        RADIUS, RAD0, RELDX, RESTOR, STEP, STGLIM, STLSTG, TOOBIG,
     5        TUNER4, TUNER5, VNEED, XIRC, X0
C
C  ***  IV SUBSCRIPT VALUES  ***
C
C/6
C     DATA CNVCOD/55/, DG/37/, G0/48/, INITH/25/, IRC/29/, KAGQT/33/,
C    1     MODE/35/, MODEL/5/, MXFCAL/17/, MXITER/18/, NFCALL/6/,
C    2     NFGCAL/7/, NGCALL/30/, NITER/31/, NWTSTP/34/, RADINC/8/,
C    3     RESTOR/9/, STEP/40/, STGLIM/11/, STLSTG/41/, TOOBIG/2/,
C    4     VNEED/4/, XIRC/13/, X0/43/
C/7
      PARAMETER (CNVCOD=55, DG=37, G0=48, INITH=25, IRC=29, KAGQT=33,
     1           MODE=35, MODEL=5, MXFCAL=17, MXITER=18, NFCALL=6,
     2           NFGCAL=7, NGCALL=30, NITER=31, NWTSTP=34, RADINC=8,
     3           RESTOR=9, STEP=40, STGLIM=11, STLSTG=41, TOOBIG=2,
     4           VNEED=4, XIRC=13, X0=43)
C/
C
C  ***  V SUBSCRIPT VALUES  ***
C
C/6
C     DATA DGNORM/1/, DINIT/38/, DSTNRM/2/, DST0/3/, F/10/, F0/13/,
C    1     FDIF/11/, GTHG/44/, GTSTEP/4/, INCFAC/23/, LMAT/42/,
C    2     LMAX0/35/, LMAXS/36/, NEXTV/47/, NREDUC/6/, PREDUC/7/,
C    3     RADFAC/16/, RADIUS/8/, RAD0/9/, RELDX/17/, TUNER4/29/,
C    4     TUNER5/30/
C/7
      PARAMETER (DGNORM=1, DINIT=38, DSTNRM=2, DST0=3, F=10, F0=13,
     1           FDIF=11, GTHG=44, GTSTEP=4, INCFAC=23, LMAT=42,
     2           LMAX0=35, LMAXS=36, NEXTV=47, NREDUC=6, PREDUC=7,
     3           RADFAC=16, RADIUS=8, RAD0=9, RELDX=17, TUNER4=29,
     4           TUNER5=30)
C/
C
C/6
C     DATA HALF/0.5D+0/, NEGONE/-1.D+0/, ONE/1.D+0/, ONEP2/1.2D+0/,
C    1     ZERO/0.D+0/
C/7
      PARAMETER (HALF=0.5D+0, NEGONE=-1.D+0, ONE=1.D+0, ONEP2=1.2D+0,
     1           ZERO=0.D+0)
C/
C
C+++++++++++++++++++++++++++++++  BODY  ++++++++++++++++++++++++++++++++
C
      I = IV(1)
      IF (I .EQ. 1) GO TO 50
      IF (I .EQ. 2) GO TO 60
C
C  ***  CHECK VALIDITY OF IV AND V INPUT VALUES  ***
C
      IF (IV(1) .EQ. 0) CALL DIVSET(2, IV, LIV, LV, V)
      IF (IV(1) .EQ. 12 .OR. IV(1) .EQ. 13)
     1     IV(VNEED) = IV(VNEED) + N*(N+13)/2
      CALL DPARCK(2, D, IV, LIV, LV, N, V)
      I = IV(1) - 2
      IF (I .GT. 12) GO TO 999
      GO TO (190, 190, 190, 190, 190, 190, 120, 90, 120, 10, 10, 20), I
C
C  ***  STORAGE ALLOCATION  ***
C
 10   L = IV(LMAT)
      IV(X0) = L + N*(N+1)/2
      IV(STEP) = IV(X0) + N
      IV(STLSTG) = IV(STEP) + N
      IV(G0) = IV(STLSTG) + N
      IV(NWTSTP) = IV(G0) + N
      IV(DG) = IV(NWTSTP) + N
      IV(NEXTV) = IV(DG) + N
      IF (IV(1) .NE. 13) GO TO 20
         IV(1) = 14
         GO TO 999
C
C  ***  INITIALIZATION  ***
C
 20   IV(NITER) = 0
      IV(NFCALL) = 1
      IV(NGCALL) = 1
      IV(NFGCAL) = 1
      IV(MODE) = -1
      IV(MODEL) = 1
      IV(STGLIM) = 1
      IV(TOOBIG) = 0
      IV(CNVCOD) = 0
      IV(RADINC) = 0
      V(RAD0) = ZERO
      IF (V(DINIT) .GE. ZERO) CALL DV7SCP(N, D, V(DINIT))
      IF (IV(INITH) .NE. 1) GO TO 40
C
C     ***  SET THE INITIAL HESSIAN APPROXIMATION TO DIAG(D)**-2  ***
C
         L = IV(LMAT)
         CALL DV7SCP(N*(N+1)/2, V(L), ZERO)
         K = L - 1
         DO 30 I = 1, N
              K = K + I
              T = D(I)
              IF (T .LE. ZERO) T = ONE
              V(K) = T
 30           CONTINUE
C
C  ***  COMPUTE INITIAL FUNCTION VALUE  ***
C
 40   IV(1) = 1
      GO TO 999
C
 50   V(F) = FX
      IF (IV(MODE) .GE. 0) GO TO 190
      V(F0) = FX
      IV(1) = 2
      IF (IV(TOOBIG) .EQ. 0) GO TO 999
         IV(1) = 63
         GO TO 350
C
C  ***  MAKE SURE GRADIENT COULD BE COMPUTED  ***
C
 60   IF (IV(TOOBIG) .EQ. 0) GO TO 70
         IV(1) = 65
         GO TO 350
C
 70   DG1 = IV(DG)
      CALL DV7VMP(N, V(DG1), G, D, -1)
      V(DGNORM) = DV2NRM(N, V(DG1))
C
      IF (IV(CNVCOD) .NE. 0) GO TO 340
      IF (IV(MODE) .EQ. 0) GO TO 300
C
C  ***  ALLOW FIRST STEP TO HAVE SCALED 2-NORM AT MOST V(LMAX0)  ***
C
      V(RADIUS) = V(LMAX0)
C
      IV(MODE) = 0
C
C
C-----------------------------  MAIN LOOP  -----------------------------
C
C
C  ***  PRINT ITERATION SUMMARY, CHECK ITERATION LIMIT  ***
C
 80   CALL DITSUM(D, G, IV, LIV, LV, N, V, X)
 90   K = IV(NITER)
      IF (K .LT. IV(MXITER)) GO TO 100
         IV(1) = 10
         GO TO 350
C
C  ***  UPDATE RADIUS  ***
C
 100  IV(NITER) = K + 1
      IF (K .GT. 0) V(RADIUS) = V(RADFAC) * V(DSTNRM)
C
C  ***  INITIALIZE FOR START OF NEXT ITERATION  ***
C
      G01 = IV(G0)
      X01 = IV(X0)
      V(F0) = V(F)
      IV(IRC) = 4
      IV(KAGQT) = -1
C
C     ***  COPY X TO X0, G TO G0  ***
C
      CALL DV7CPY(N, V(X01), X)
      CALL DV7CPY(N, V(G01), G)
C
C  ***  CHECK STOPX AND FUNCTION EVALUATION LIMIT  ***
C
 110  IF (.NOT. STOPX(DUMMY)) GO TO 130
         IV(1) = 11
         GO TO 140
C
C     ***  COME HERE WHEN RESTARTING AFTER FUNC. EVAL. LIMIT OR STOPX.
C
 120  IF (V(F) .GE. V(F0)) GO TO 130
         V(RADFAC) = ONE
         K = IV(NITER)
         GO TO 100
C
 130  IF (IV(NFCALL) .LT. IV(MXFCAL)) GO TO 150
         IV(1) = 9
 140     IF (V(F) .GE. V(F0)) GO TO 350
C
C        ***  IN CASE OF STOPX OR FUNCTION EVALUATION LIMIT WITH
C        ***  IMPROVED V(F), EVALUATE THE GRADIENT AT X.
C
              IV(CNVCOD) = IV(1)
              GO TO 290
C
C. . . . . . . . . . . . .  COMPUTE CANDIDATE STEP  . . . . . . . . . .
C
 150  STEP1 = IV(STEP)
      DG1 = IV(DG)
      NWTST1 = IV(NWTSTP)
      IF (IV(KAGQT) .GE. 0) GO TO 160
         L = IV(LMAT)
         CALL DL7IVM(N, V(NWTST1), V(L), G)
         V(NREDUC) = HALF * DD7TPR(N, V(NWTST1), V(NWTST1))
         CALL DL7ITV(N, V(NWTST1), V(L), V(NWTST1))
         CALL DV7VMP(N, V(STEP1), V(NWTST1), D, 1)
         V(DST0) = DV2NRM(N, V(STEP1))
         CALL DV7VMP(N, V(DG1), V(DG1), D, -1)
         CALL DL7TVM(N, V(STEP1), V(L), V(DG1))
         V(GTHG) = DV2NRM(N, V(STEP1))
         IV(KAGQT) = 0
 160  CALL DD7DOG(V(DG1), LV, N, V(NWTST1), V(STEP1), V)
      IF (IV(IRC) .NE. 6) GO TO 170
         IF (IV(RESTOR) .NE. 2) GO TO 190
         RSTRST = 2
         GO TO 200
C
C  ***  CHECK WHETHER EVALUATING F(X0 + STEP) LOOKS WORTHWHILE  ***
C
 170  IV(TOOBIG) = 0
      IF (V(DSTNRM) .LE. ZERO) GO TO 190
      IF (IV(IRC) .NE. 5) GO TO 180
      IF (V(RADFAC) .LE. ONE) GO TO 180
      IF (V(PREDUC) .GT. ONEP2 * V(FDIF)) GO TO 180
         IF (IV(RESTOR) .NE. 2) GO TO 190
         RSTRST = 0
         GO TO 200
C
C  ***  COMPUTE F(X0 + STEP)  ***
C
 180  X01 = IV(X0)
      STEP1 = IV(STEP)
      CALL DV2AXY(N, X, ONE, V(STEP1), V(X01))
      IV(NFCALL) = IV(NFCALL) + 1
      IV(1) = 1
      GO TO 999
C
C. . . . . . . . . . . . .  ASSESS CANDIDATE STEP  . . . . . . . . . . .
C
 190  RSTRST = 3
 200  X01 = IV(X0)
      V(RELDX) = DRLDST(N, D, X, V(X01))
      CALL DA7SST(IV, LIV, LV, V)
      STEP1 = IV(STEP)
      LSTGST = IV(STLSTG)
      I = IV(RESTOR) + 1
      GO TO (240, 210, 220, 230), I
 210  CALL DV7CPY(N, X, V(X01))
      GO TO 240
 220   CALL DV7CPY(N, V(LSTGST), V(STEP1))
       GO TO 240
 230     CALL DV7CPY(N, V(STEP1), V(LSTGST))
         CALL DV2AXY(N, X, ONE, V(STEP1), V(X01))
         V(RELDX) = DRLDST(N, D, X, V(X01))
         IV(RESTOR) = RSTRST
C
 240  K = IV(IRC)
      GO TO (250,280,280,280,250,260,270,270,270,270,270,270,330,300), K
C
C     ***  RECOMPUTE STEP WITH CHANGED RADIUS  ***
C
 250     V(RADIUS) = V(RADFAC) * V(DSTNRM)
         GO TO 110
C
C  ***  COMPUTE STEP OF LENGTH V(LMAXS) FOR SINGULAR CONVERGENCE TEST.
C
 260  V(RADIUS) = V(LMAXS)
      GO TO 150
C
C  ***  CONVERGENCE OR FALSE CONVERGENCE  ***
C
 270  IV(CNVCOD) = K - 4
      IF (V(F) .GE. V(F0)) GO TO 340
         IF (IV(XIRC) .EQ. 14) GO TO 340
              IV(XIRC) = 14
C
C. . . . . . . . . . . .  PROCESS ACCEPTABLE STEP  . . . . . . . . . . .
C
 280  IF (IV(IRC) .NE. 3) GO TO 290
         STEP1 = IV(STEP)
         TEMP1 = IV(STLSTG)
C
C     ***  SET  TEMP1 = HESSIAN * STEP  FOR _USE_ IN GRADIENT TESTS  ***
C
         L = IV(LMAT)
         CALL DL7TVM(N, V(TEMP1), V(L), V(STEP1))
         CALL DL7VML(N, V(TEMP1), V(L), V(TEMP1))
C
C  ***  COMPUTE GRADIENT  ***
C
 290  IV(NGCALL) = IV(NGCALL) + 1
      IV(1) = 2
      GO TO 999
C
C  ***  INITIALIZATIONS -- G0 = G - G0, ETC.  ***
C
 300  G01 = IV(G0)
      CALL DV2AXY(N, V(G01), NEGONE, V(G01), G)
      STEP1 = IV(STEP)
      TEMP1 = IV(STLSTG)
      IF (IV(IRC) .NE. 3) GO TO 320
C
C  ***  SET V(RADFAC) BY GRADIENT TESTS  ***
C
C     ***  SET  TEMP1 = DIAG(D)**-1 * (HESSIAN*STEP + (G(X0)-G(X)))  ***
C
         CALL DV2AXY(N, V(TEMP1), NEGONE, V(G01), V(TEMP1))
         CALL DV7VMP(N, V(TEMP1), V(TEMP1), D, -1)
C
C        ***  DO GRADIENT TESTS  ***
C
         IF (DV2NRM(N, V(TEMP1)) .LE. V(DGNORM) * V(TUNER4))
     1                  GO TO 310
              IF (DD7TPR(N, G, V(STEP1))
     1                  .GE. V(GTSTEP) * V(TUNER5))  GO TO 320
 310               V(RADFAC) = V(INCFAC)
C
C  ***  UPDATE H, LOOP  ***
C
 320  W = IV(NWTSTP)
      Z = IV(X0)
      L = IV(LMAT)
      CALL DW7ZBF(V(L), N, V(STEP1), V(W), V(G01), V(Z))
C
C     ** _USE_ THE N-VECTORS STARTING AT V(STEP1) AND V(G01) FOR SCRATCH..
      CALL DL7UPD(V(TEMP1), V(STEP1), V(L), V(G01), V(L), N, V(W), V(Z))
      IV(1) = 2
      GO TO 80
C
C. . . . . . . . . . . . . .  MISC. DETAILS  . . . . . . . . . . . . . .
C
C  ***  BAD PARAMETERS TO ASSESS  ***
C
 330  IV(1) = 64
      GO TO 350
C
C  ***  PRINT SUMMARY OF FINAL ITERATION AND OTHER REQUESTED ITEMS  ***
C
 340  IV(1) = IV(CNVCOD)
      IV(CNVCOD) = 0
 350  CALL DITSUM(D, G, IV, LIV, LV, N, V, X)
C
 999  RETURN
C
C  ***  LAST LINE OF DRMNG FOLLOWS  ***
      END
