LCOV - code coverage report
Current view: top level - shared/common/src/28_numeric_noabirule - m_slsqp.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 946 0
Test Date: 2026-09-20 18:56:22 Functions: 0.0 % 19 0

            Line data    Source code
       1              : !!****m* ABINIT/m_slsqp
       2              : !! NAME
       3              : !! m_slsqp
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains the SLSQP optimization routine.
       7              : !! This was taken from scipy.
       8              : !!
       9              : !! COPYRIGHT
      10              : !! Copyright (c) 2001-2002 Enthought, Inc. 2003-2024, SciPy Developers.
      11              : !! All rights reserved.
      12              : !!
      13              : !! Redistribution and use in source and binary forms, with or without
      14              : !! modification, are permitted provided that the following conditions
      15              : !! are met:
      16              : !!
      17              : !! 1. Redistributions of source code must retain the above copyright
      18              : !!    notice, this list of conditions and the following disclaimer.
      19              : !!
      20              : !! 2. Redistributions in binary form must reproduce the above
      21              : !!    copyright notice, this list of conditions and the following
      22              : !!    disclaimer in the documentation and/or other materials provided
      23              : !!    with the distribution.
      24              : !!
      25              : !! 3. Neither the name of the copyright holder nor the names of its
      26              : !!    contributors may be used to endorse or promote products derived
      27              : !!    from this software without specific prior written permission.
      28              : !!
      29              : !! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      30              : !! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      31              : !! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      32              : !! A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      33              : !! OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      34              : !! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      35              : !! LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      36              : !! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      37              : !! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      38              : !! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      39              : !! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      40              : !!
      41              : !! This file is distributed under the terms of the
      42              : !! GNU General Public License, see ~abinit/COPYING
      43              : !! or http://www.gnu.org/copyleft/gpl.txt .
      44              : !!
      45              : !! SOURCE
      46              : 
      47              : #if defined HAVE_CONFIG_H
      48              : #include "config.h"
      49              : #endif
      50              : 
      51              : #include "abi_common.h"
      52              : 
      53              : MODULE m_slsqp
      54              : 
      55              :  implicit none
      56              : 
      57              :  private
      58              : 
      59              :  public :: slsqp
      60              : 
      61              : CONTAINS  !========================================================================================
      62              : !!***
      63              : 
      64              : !C
      65              : !C      ALGORITHM 733, COLLECTED ALGORITHMS FROM ACM.
      66              : !C      TRANSACTIONS ON MATHEMATICAL SOFTWARE,
      67              : !C      VOL. 20, NO. 3, SEPTEMBER, 1994, PP. 262-281.
      68              : !C      https://doi.org/10.1145/192115.192124
      69              : !C
      70              : !C
      71              : !C      https://web.archive.org/web/20170106155705/http://permalink.gmane.org/gmane.comp.python.scientific.devel/6725
      72              : !C      ------
      73              : !C      From: Deborah Cotton <cotton@hq.acm.org>
      74              : !C      Date: Fri, 14 Sep 2007 12:35:55 -0500
      75              : !C      Subject: RE: Algorithm License requested
      76              : !C      To: Alan Isaac
      77              : !C
      78              : !C      Prof. Issac,
      79              : !C
      80              : !C      In that case, then because the author consents to [the ACM] releasing
      81              : !C      the code currently archived at http://www.netlib.org/toms/733 under the
      82              : !C      BSD license, the ACM hereby releases this code under the BSD license.
      83              : !C
      84              : !C      Regards,
      85              : !C
      86              : !C      Deborah Cotton, Copyright & Permissions
      87              : !C      ACM Publications
      88              : !C      2 Penn Plaza, Suite 701**
      89              : !C      New York, NY 10121-0701
      90              : !C      permissions@acm.org
      91              : !C      212.869.7440 ext. 652
      92              : !C      Fax. 212.869.0481
      93              : !C      ------
      94              : !C
      95              : 
      96              : !************************************************************************
      97              : !*                              optimizer                               *
      98              : !************************************************************************
      99              : 
     100            0 :       SUBROUTINE slsqp (m, meq, la, n, x, xl, xu, f, c, g, a,  &
     101            0 :                        acc, iter, mode, w, l_w, jw, l_jw,  &
     102              :                        alpha, f0, gs, h1, h2, h3, h4, t, t0, tol, &
     103              :                        iexact, incons, ireset, itermx, line, &
     104              :                        n1, n2, n3)
     105              : 
     106              : !C   SLSQP       S EQUENTIAL  L EAST  SQ UARES  P ROGRAMMING
     107              : !C            TO SOLVE GENERAL NONLINEAR OPTIMIZATION PROBLEMS
     108              : 
     109              : !C***********************************************************************
     110              : !C*                                                                     *
     111              : !C*                                                                     *
     112              : !C*            A NONLINEAR PROGRAMMING METHOD WITH                      *
     113              : !C*            QUADRATIC  PROGRAMMING  SUBPROBLEMS                      *
     114              : !C*                                                                     *
     115              : !C*                                                                     *
     116              : !C*  THIS SUBROUTINE SOLVES THE GENERAL NONLINEAR PROGRAMMING PROBLEM   *
     117              : !C*                                                                     *
     118              : !C*            MINIMIZE    F(X)                                         *
     119              : !C*                                                                     *
     120              : !C*            SUBJECT TO  C (X) .EQ. 0  ,  J = 1,...,MEQ               *
     121              : !C*                         J                                           *
     122              : !C*                                                                     *
     123              : !C*                        C (X) .GE. 0  ,  J = MEQ+1,...,M             *
     124              : !C*                         J                                           *
     125              : !C*                                                                     *
     126              : !C*                        XL .LE. X .LE. XU , I = 1,...,N.             *
     127              : !C*                          I      I       I                           *
     128              : !C*                                                                     *
     129              : !C*  THE ALGORITHM IMPLEMENTS THE METHOD OF HAN AND POWELL              *
     130              : !C*  WITH BFGS-UPDATE OF THE B-MATRIX AND L1-TEST FUNCTION              *
     131              : !C*  WITHIN THE STEPLENGTH ALGORITHM.                                   *
     132              : !C*                                                                     *
     133              : !C*    PARAMETER DESCRIPTION:                                           *
     134              : !C*    ( * MEANS THIS PARAMETER WILL BE CHANGED DURING CALCULATION )    *
     135              : !C*                                                                     *
     136              : !C*    M              IS THE TOTAL NUMBER OF CONSTRAINTS, M .GE. 0      *
     137              : !C*    MEQ            IS THE NUMBER OF EQUALITY CONSTRAINTS, MEQ .GE. 0 *
     138              : !C*    LA             SEE A, LA .GE. MAX(M,1)                           *
     139              : !C*    N              IS THE NUMBER OF VARIBLES, N .GE. 1               *
     140              : !C*  * X()            X() STORES THE CURRENT ITERATE OF THE N VECTOR X  *
     141              : !C*                   ON ENTRY X() MUST BE INITIALIZED. ON EXIT X()     *
     142              : !C*                   STORES THE SOLUTION VECTOR X IF MODE = 0.         *
     143              : !C*    XL()           XL() STORES AN N VECTOR OF LOWER BOUNDS XL TO X.  *
     144              : !C*                   ELEMENTS MAY BE NAN TO INDICATE NO LOWER BOUND.   *
     145              : !C*    XU()           XU() STORES AN N VECTOR OF UPPER BOUNDS XU TO X.  *
     146              : !C*                   ELEMENTS MAY BE NAN TO INDICATE NO UPPER BOUND.   *
     147              : !C*    F              IS THE VALUE OF THE OBJECTIVE FUNCTION.           *
     148              : !C*    C()            C() STORES THE M VECTOR C OF CONSTRAINTS,         *
     149              : !C*                   EQUALITY CONSTRAINTS (IF ANY) FIRST.              *
     150              : !C*                   DIMENSION OF C MUST BE GREATER OR EQUAL LA,       *
     151              : !C*                   which must be GREATER OR EQUAL MAX(1,M).          *
     152              : !C*    G()            G() STORES THE N VECTOR G OF PARTIALS OF THE      *
     153              : !C*                   OBJECTIVE FUNCTION; DIMENSION OF G MUST BE        *
     154              : !C*                   GREATER OR EQUAL N+1.                             *
     155              : !C*    A(),LA,M,N     THE LA BY N + 1 ARRAY A() STORES                  *
     156              : !C*                   THE M BY N MATRIX A OF CONSTRAINT NORMALS.        *
     157              : !C*                   A() HAS FIRST DIMENSIONING PARAMETER LA,          *
     158              : !C*                   WHICH MUST BE GREATER OR EQUAL MAX(1,M).          *
     159              : !C*    F,C,G,A        MUST ALL BE SET BY THE USER BEFORE EACH CALL.     *
     160              : !C*  * ACC            ABS(ACC) CONTROLS THE FINAL ACCURACY.             *
     161              : !C*                   IF ACC .LT. ZERO AN EXACT LINESEARCH IS PERFORMED,*
     162              : !C*                   OTHERWISE AN ARMIJO-TYPE LINESEARCH IS USED.      *
     163              : !C*  * ITER           PRESCRIBES THE MAXIMUM NUMBER OF ITERATIONS.      *
     164              : !C*                   ON EXIT ITER INDICATES THE NUMBER OF ITERATIONS.  *
     165              : !C*  * MODE           MODE CONTROLS CALCULATION:                        *
     166              : !C*                   REVERSE COMMUNICATION IS USED IN THE SENSE THAT   *
     167              : !C*                   THE PROGRAM IS INITIALIZED BY MODE = 0; THEN IT IS*
     168              : !C*                   TO BE CALLED REPEATEDLY BY THE USER UNTIL A RETURN*
     169              : !C*                   WITH MODE .NE. IABS(1) TAKES PLACE.               *
     170              : !C*                   IF MODE = -1 GRADIENTS HAVE TO BE CALCULATED,     *
     171              : !C*                   WHILE WITH MODE = 1 FUNCTIONS HAVE TO BE CALCULATED
     172              : !C*                   MODE MUST NOT BE CHANGED BETWEEN SUBSEQUENT CALLS *
     173              : !C*                   OF SQP.                                           *
     174              : !C*                   EVALUATION MODES:                                 *
     175              : !C*        MODE = -1: GRADIENT EVALUATION, (G&A)                        *
     176              : !C*                0: ON ENTRY: INITIALIZATION, (F,G,C&A)               *
     177              : !C*                   ON EXIT : REQUIRED ACCURACY FOR SOLUTION OBTAINED *
     178              : !C*                1: FUNCTION EVALUATION, (F&C)                        *
     179              : !C*                                                                     *
     180              : !C*                   FAILURE MODES:                                    *
     181              : !C*                2: NUMBER OF EQUALITY CONSTRAINTS LARGER THAN N      *
     182              : !C*                3: MORE THAN 3*N ITERATIONS IN LSQ SUBPROBLEM        *
     183              : !C*                4: INEQUALITY CONSTRAINTS INCOMPATIBLE               *
     184              : !C*                5: SINGULAR MATRIX E IN LSQ SUBPROBLEM               *
     185              : !C*                6: SINGULAR MATRIX C IN LSQ SUBPROBLEM               *
     186              : !C*                7: RANK-DEFICIENT EQUALITY CONSTRAINT SUBPROBLEM HFTI*
     187              : !C*                8: POSITIVE DIRECTIONAL DERIVATIVE FOR LINESEARCH    *
     188              : !C*                9: MORE THAN ITER ITERATIONS IN SQP                  *
     189              : !C*             >=10: WORKING SPACE W OR JW TOO SMALL,                  *
     190              : !C*                   W SHOULD BE ENLARGED TO L_W=MODE/1000             *
     191              : !C*                   JW SHOULD BE ENLARGED TO L_JW=MODE-1000*L_W       *
     192              : !C*  * W(), L_W       W() IS A ONE DIMENSIONAL WORKING SPACE,           *
     193              : !C*                   THE LENGTH L_W OF WHICH SHOULD BE AT LEAST        *
     194              : !C*                   (3*N1+M)*(N1+1)                        for LSQ    *
     195              : !C*                  +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ         for LSI    *
     196              : !C*                  +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1       for LSEI   *
     197              : !C*                  + N1*N/2 + 2*M + 3*N + 3*N1 + 1         for SLSQPB *
     198              : !C*                   with MINEQ = M - MEQ + 2*N1  &  N1 = N+1          *
     199              : !C*        NOTICE:    FOR PROPER DIMENSIONING OF W IT IS RECOMMENDED TO *
     200              : !C*                   COPY THE FOLLOWING STATEMENTS INTO THE HEAD OF    *
     201              : !C*                   THE CALLING PROGRAM (AND REMOVE THE COMMENT C)    *
     202              : !c#######################################################################
     203              : !C     INTEGER LEN_W, LEN_JW, M, N, N1, MEQ, MINEQ
     204              : !C     PARAMETER (M=... , MEQ=... , N=...  )
     205              : !C     PARAMETER (N1= N+1, MINEQ= M-MEQ+N1+N1)
     206              : !C     PARAMETER (LEN_W=
     207              : !c    $           (3*N1+M)*(N1+1)
     208              : !c    $          +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ
     209              : !c    $          +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1
     210              : !c    $          +(N+1)*N/2 + 2*M + 3*N + 3*N1 + 1,
     211              : !c    $           LEN_JW=MINEQ)
     212              : !C     DOUBLE PRECISION W(LEN_W)
     213              : !C     INTEGER          JW(LEN_JW)
     214              : !c#######################################################################
     215              : !C*                   THE FIRST M+N+N*N1/2 ELEMENTS OF W MUST NOT BE    *
     216              : !C*                   CHANGED BETWEEN SUBSEQUENT CALLS OF SLSQP.        *
     217              : !C*                   ON RETURN W(1) ... W(M) CONTAIN THE MULTIPLIERS   *
     218              : !C*                   ASSOCIATED WITH THE GENERAL CONSTRAINTS, WHILE    *
     219              : !C*                   W(M+1) ... W(M+N(N+1)/2) STORE THE CHOLESKY FACTOR*
     220              : !C*                   L*D*L(T) OF THE APPROXIMATE HESSIAN OF THE        *
     221              : !C*                   LAGRANGIAN COLUMNWISE DENSE AS LOWER TRIANGULAR   *
     222              : !C*                   UNIT MATRIX L WITH D IN ITS 'DIAGONAL' and        *
     223              : !C*                   W(M+N(N+1)/2+N+2 ... W(M+N(N+1)/2+N+2+M+2N)       *
     224              : !C*                   CONTAIN THE MULTIPLIERS ASSOCIATED WITH ALL       *
     225              : !C*                   ALL CONSTRAINTS OF THE QUADRATIC PROGRAM FINDING  *
     226              : !C*                   THE SEARCH DIRECTION TO THE SOLUTION X*           *
     227              : !C*  * JW(), L_JW     JW() IS A ONE DIMENSIONAL INTEGER WORKING SPACE   *
     228              : !C*                   THE LENGTH L_JW OF WHICH SHOULD BE AT LEAST       *
     229              : !C*                   MINEQ                                             *
     230              : !C*                   with MINEQ = M - MEQ + 2*N1  &  N1 = N+1          *
     231              : !C*                                                                     *
     232              : !C*  THE USER HAS TO PROVIDE THE FOLLOWING SUBROUTINES:                 *
     233              : !C*     LDL(N,A,Z,SIG,W) :   UPDATE OF THE LDL'-FACTORIZATION.          *
     234              : !C*     LINMIN(A,B,F,TOL) :  LINESEARCH ALGORITHM IF EXACT = 1          *
     235              : !C*     LSQ(M,MEQ,LA,N,NC,C,D,A,B,XL,XU,X,LAMBDA,W,....) :              *
     236              : !C*                                                                     *
     237              : !C*        SOLUTION OF THE QUADRATIC PROGRAM                            *
     238              : !C*                QPSOL IS RECOMMENDED:                                *
     239              : !C*     PE GILL, W MURRAY, MA SAUNDERS, MH WRIGHT:                      *
     240              : !C*     USER'S GUIDE FOR SOL/QPSOL:                                     *
     241              : !C*     A FORTRAN PACKAGE FOR QUADRATIC PROGRAMMING,                    *
     242              : !C*     TECHNICAL REPORT SOL 83-7, JULY 1983                            *
     243              : !C*     DEPARTMENT OF OPERATIONS RESEARCH, STANFORD UNIVERSITY          *
     244              : !C*     STANFORD, CA 94305                                              *
     245              : !C*     QPSOL IS THE MOST ROBUST AND EFFICIENT QP-SOLVER                *
     246              : !C*     AS IT ALLOWS WARM STARTS WITH PROPER WORKING SETS               *
     247              : !C*                                                                     *
     248              : !C*     IF IT IS NOT AVAILABLE USE LSEI, A CONSTRAINT LINEAR LEAST      *
     249              : !C*     SQUARES SOLVER IMPLEMENTED USING THE SOFTWARE HFTI, LDP, NNLS   *
     250              : !C*     FROM C.L. LAWSON, R.J.HANSON: SOLVING LEAST SQUARES PROBLEMS,   *
     251              : !C*     PRENTICE HALL, ENGLEWOOD CLIFFS, 1974.                          *
     252              : !C*     LSEI COMES WITH THIS PACKAGE, together with all necessary SR's. *
     253              : !C*                                                                     *
     254              : !C*     TOGETHER WITH A COUPLE OF SUBROUTINES FROM BLAS LEVEL 1         *
     255              : !C*                                                                     *
     256              : !C*     SQP IS HEAD SUBROUTINE FOR BODY SUBROUTINE SQPBDY               *
     257              : !C*     IN WHICH THE ALGORITHM HAS BEEN IMPLEMENTED.                    *
     258              : !C*                                                                     *
     259              : !C*  IMPLEMENTED BY: DIETER KRAFT, DFVLR OBERPFAFFENHOFEN               *
     260              : !C*  as described in Dieter Kraft: A Software Package for               *
     261              : !C*                                Sequential Quadratic Programming     *
     262              : !C*                                DFVLR-FB 88-28, 1988                 *
     263              : !C*  which should be referenced if the user publishes results of SLSQP  *
     264              : !C*                                                                     *
     265              : !C*  DATE:           APRIL - OCTOBER, 1981.                             *
     266              : !C*  STATUS:         DECEMBER, 31-ST, 1984.                             *
     267              : !C*  STATUS:         MARCH   , 21-ST, 1987, REVISED TO FORTRAN 77       *
     268              : !C*  STATUS:         MARCH   , 20-th, 1989, REVISED TO MS-FORTRAN       *
     269              : !C*  STATUS:         APRIL   , 14-th, 1989, HESSE   in-line coded       *
     270              : !C*  STATUS:         FEBRUARY, 28-th, 1991, FORTRAN/2 Version 1.04      *
     271              : !C*                                         accepts Statement Functions *
     272              : !C*  STATUS:         MARCH   ,  1-st, 1991, tested with SALFORD         *
     273              : !C*                                         FTN77/386 COMPILER VERS 2.40*
     274              : !C*                                         in protected mode           *
     275              : !C*                                                                     *
     276              : !C***********************************************************************
     277              : !C*                                                                     *
     278              : !C*  Copyright 1991: Dieter Kraft, FHM                                  *
     279              : !C*                                                                     *
     280              : !C***********************************************************************
     281              : 
     282              :       INTEGER          il, im, ir, is, iter, iu, iv, iw, ix, l_w, l_jw, &
     283              :                        jw(l_jw), la, m, meq, mineq, mode, n
     284              : 
     285              :       DOUBLE PRECISION acc, a(la,n+1), c(la), f, g(n+1), &
     286              :                        x(n), xl(n), xu(n), w(l_w)
     287              : 
     288              :       INTEGER          iexact, incons, ireset, itermx, line, n1, n2, n3
     289              : 
     290              :       DOUBLE PRECISION alpha, f0, gs, h1, h2, h3, h4, t, t0, tol
     291              : 
     292              : !c     dim(W) =         N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1)  for LSQ
     293              : !c                    +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ          for LSI
     294              : !c                    +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1        for LSEI
     295              : !c                    + N1*N/2 + 2*M + 3*N +3*N1 + 1           for SLSQPB
     296              : !c                      with MINEQ = M - MEQ + 2*N1  &  N1 = N+1
     297              : 
     298              : !C   CHECK LENGTH OF WORKING ARRAYS
     299              : 
     300            0 :       n1 = n+1
     301            0 :       mineq = m-meq+n1+n1
     302              :       il = (3*n1+m)*(n1+1) +  &
     303              :       (n1-meq+1)*(mineq+2) + 2*mineq + &
     304              :       (n1+mineq)*(n1-meq)  + 2*meq +  &
     305            0 :       n1*n/2 + 2*m + 3*n + 4*n1 + 1
     306            0 :       im = MAX(mineq, n1-meq)
     307            0 :       IF (l_w .LT. il .OR. l_jw .LT. im) THEN
     308            0 :           mode = 1000*MAX(10,il)
     309            0 :           mode = mode+MAX(10,im)
     310            0 :           RETURN
     311              :       ENDIF
     312              : 
     313              : !C   PREPARE DATA FOR CALLING SQPBDY  -  INITIAL ADDRESSES IN W
     314              : 
     315            0 :       im = 1
     316            0 :       il = im + MAX(1,m)
     317            0 :       il = im + la
     318            0 :       ix = il + n1*n/2 + 1
     319            0 :       ir = ix + n
     320            0 :       is = ir + n + n + MAX(1,m)
     321            0 :       is = ir + n + n + la
     322            0 :       iu = is + n1
     323            0 :       iv = iu + n1
     324            0 :       iw = iv + n1
     325              : 
     326              :       CALL slsqpb  (m, meq, la, n, x, xl, xu, f, c, g, a, acc, iter,  &
     327              :        mode, w(ir), w(il), w(ix), w(im), w(is), w(iu), w(iv), w(iw), jw, &
     328              :        alpha, f0, gs, h1, h2, h3, h4, t, t0, tol, &
     329              :        iexact, incons, ireset, itermx, line, &
     330            0 :        n1, n2, n3)
     331              : 
     332              :       END SUBROUTINE slsqp
     333              : 
     334            0 :       SUBROUTINE slsqpb (m, meq, la, n, x, xl, xu, f, c, g, a, acc,  &
     335            0 :                          iter, mode, r, l, x0, mu, s, u, v, w, iw, &
     336              :                          alpha, f0, gs, h1, h2, h3, h4, t, t0, tol, &
     337              :                          iexact, incons, ireset, itermx, line, &
     338              :                          n1, n2, n3)
     339              : 
     340              : !C   NONLINEAR PROGRAMMING BY SOLVING SEQUENTIALLY QUADRATIC PROGRAMS
     341              : 
     342              : !C        -  L1 - LINE SEARCH,  POSITIVE DEFINITE  BFGS UPDATE  -
     343              : 
     344              : !C                      BODY SUBROUTINE FOR SLSQP
     345              : 
     346              :       INTEGER          iw(*), i, iexact, incons, ireset, iter, itermx, &
     347              :                        k, j, la, line, m, meq, mode, n, n1, n2, n3
     348              :       LOGICAL          badlin
     349              : 
     350              :       DOUBLE PRECISION a(la,n+1), c(la), g(n+1), l((n+1)*(n+2)/2), &
     351              :                        mu(la), r(m+n+n+2), s(n+1), u(n+1), v(n+1), w(*), &
     352              :                        x(n), xl(n), xu(n), x0(n), &
     353              :                        acc, alfmin, alpha, f, f0, gs, h1, h2, h3, h4, &
     354              :                        hun, one, t, t0, ten, tol, two, ZERO
     355              : 
     356              : !c     dim(W) =         N1*(N1+1) + MEQ*(N1+1) + MINEQ*(N1+1)  for LSQ
     357              : !c                     +(N1-MEQ+1)*(MINEQ+2) + 2*MINEQ
     358              : !c                     +(N1+MINEQ)*(N1-MEQ) + 2*MEQ + N1       for LSEI
     359              : !c                      with MINEQ = M - MEQ + 2*N1  &  N1 = N+1
     360              : 
     361              :       DATA             ZERO /0.0d0/, one /1.0d0/, alfmin /1.0d-1/, &
     362              :                        hun /1.0d+2/, ten /1.0d+1/, two /2.0d0/
     363              : 
     364              : !C     The badlin flag keeps track whether the SQP problem on the current
     365              : !C     iteration was inconsistent or not.
     366            0 :       badlin = .false.
     367              : 
     368            0 :       IF (mode.LT.0) GO TO 260
     369            0 :       IF (mode.EQ.0) GO TO 100
     370              :       IF (mode.GT.0) GO TO 220
     371              : 
     372            0 :   100 itermx = iter
     373            0 :       IF (acc.GE.ZERO) THEN
     374            0 :           iexact = 0
     375              :       ELSE
     376            0 :           iexact = 1
     377              :       ENDIF
     378            0 :       acc = ABS(acc)
     379            0 :       tol = ten*acc
     380            0 :       iter = 0
     381            0 :       ireset = 0
     382            0 :       n1 = n + 1
     383            0 :       n2 = n1*n/2
     384            0 :       n3 = n2 + 1
     385            0 :       s(1) = ZERO
     386            0 :       mu(1) = ZERO
     387            0 :       CALL dcopy_(n, s(1),  0, s,  1)
     388            0 :       CALL dcopy_(m, mu(1), 0, mu, 1)
     389              : 
     390              : !C   RESET BFGS MATRIX
     391              : 
     392            0 :   110 ireset = ireset + 1
     393            0 :       IF (ireset.GT.5) GO TO 255
     394            0 :       l(1) = ZERO
     395            0 :       CALL dcopy_(n2, l(1), 0, l, 1)
     396            0 :       j = 1
     397            0 :       DO 120 i=1,n
     398            0 :          l(j) = one
     399            0 :          j = j + n1 - i
     400            0 :   120 CONTINUE
     401              : 
     402              : !C   MAIN ITERATION : SEARCH DIRECTION, STEPLENGTH, LDL'-UPDATE
     403              : 
     404            0 :   130 iter = iter + 1
     405            0 :       mode = 9
     406            0 :       IF (iter.GT.itermx) GO TO 330
     407              : 
     408              : !C   SEARCH DIRECTION AS SOLUTION OF QP - SUBPROBLEM
     409              : 
     410            0 :       CALL dcopy_(n, xl, 1, u, 1)
     411            0 :       CALL dcopy_(n, xu, 1, v, 1)
     412            0 :       CALL daxpy_sl(n, -one, x, 1, u, 1)
     413            0 :       CALL daxpy_sl(n, -one, x, 1, v, 1)
     414            0 :       h4 = one
     415            0 :       CALL lsq (m, meq, n , n3, la, l, g, a, c, u, v, s, r, w, iw, mode)
     416              : 
     417              : !C   AUGMENTED PROBLEM FOR INCONSISTENT LINEARIZATION
     418              : !C
     419              : !C   If it turns out that the original SQP problem is inconsistent,
     420              : !C   disallow termination with convergence on this iteration,
     421              : !C   even if the augmented problem was solved.
     422              : 
     423            0 :       badlin = .false.
     424            0 :       IF (mode.EQ.6) THEN
     425            0 :           IF (n.EQ.meq) THEN
     426            0 :               mode = 4
     427              :           ENDIF
     428              :       ENDIF
     429            0 :       IF (mode.EQ.4) THEN
     430            0 :           badlin = .true.
     431            0 :           DO 140 j=1,m
     432            0 :              IF (j.LE.meq) THEN
     433            0 :                  a(j,n1) = -c(j)
     434              :              ELSE
     435            0 :                  a(j,n1) = MAX(-c(j),ZERO)
     436              :              ENDIF
     437            0 :   140     CONTINUE
     438            0 :           s(1) = ZERO
     439            0 :           CALL dcopy_(n, s(1), 0, s, 1)
     440            0 :           h3 = ZERO
     441            0 :           g(n1) = ZERO
     442            0 :           l(n3) = hun
     443            0 :           s(n1) = one
     444            0 :           u(n1) = ZERO
     445            0 :           v(n1) = one
     446            0 :           incons = 0
     447              :   150     CALL lsq (m, meq, n1, n3, la, l, g, a, c, u, v, s, r, &
     448            0 :                     w, iw, mode)
     449            0 :           h4 = one - s(n1)
     450            0 :           IF (mode.EQ.4) THEN
     451            0 :               l(n3) = ten*l(n3)
     452            0 :               incons = incons + 1
     453            0 :               IF (incons.GT.5) GO TO 330
     454              :               GOTO 150
     455            0 :           ELSE IF (mode.NE.1) THEN
     456              :               GOTO 330
     457              :           ENDIF
     458            0 :       ELSE IF (mode.NE.1) THEN
     459              :           GOTO 330
     460              :       ENDIF
     461              : 
     462              : !C   UPDATE MULTIPLIERS FOR L1-TEST
     463              : 
     464            0 :       DO 160 i=1,n
     465            0 :          v(i) = g(i) - ddot_sl(m,a(1,i),1,r,1)
     466            0 :   160 CONTINUE
     467            0 :       f0 = f
     468            0 :       CALL dcopy_(n, x, 1, x0, 1)
     469            0 :       gs = ddot_sl(n, g, 1, s, 1)
     470            0 :       h1 = ABS(gs)
     471            0 :       h2 = ZERO
     472            0 :       DO 170 j=1,m
     473            0 :          IF (j.LE.meq) THEN
     474            0 :              h3 = c(j)
     475              :          ELSE
     476            0 :              h3 = ZERO
     477              :          ENDIF
     478            0 :          h2 = h2 + MAX(-c(j),h3)
     479            0 :          h3 = ABS(r(j))
     480            0 :          mu(j) = MAX(h3,(mu(j)+h3)/two)
     481            0 :          h1 = h1 + h3*ABS(c(j))
     482            0 :   170 CONTINUE
     483              : 
     484              : !C   CHECK CONVERGENCE
     485              : 
     486            0 :       mode = 0
     487              :       IF (h1.LT.acc .AND. h2.LT.acc .AND. .NOT. badlin  &
     488            0 :            .AND. f .EQ. f) GO TO 330
     489            0 :       h1 = ZERO
     490            0 :       DO 180 j=1,m
     491            0 :          IF (j.LE.meq) THEN
     492            0 :              h3 = c(j)
     493              :          ELSE
     494            0 :              h3 = ZERO
     495              :          ENDIF
     496            0 :          h1 = h1 + mu(j)*MAX(-c(j),h3)
     497            0 :   180 CONTINUE
     498            0 :       t0 = f + h1
     499            0 :       h3 = gs - h1*h4
     500            0 :       mode = 8
     501            0 :       IF (h3.GE.ZERO) GO TO 110
     502              : 
     503              : !C   LINE SEARCH WITH AN L1-TESTFUNCTION
     504              : 
     505            0 :       line = 0
     506            0 :       alpha = one
     507            0 :       IF (iexact.EQ.1) GOTO 210
     508              : 
     509              : !C   INEXACT LINESEARCH
     510              : 
     511            0 :   190     line = line + 1
     512            0 :           h3 = alpha*h3
     513            0 :           CALL dscal_sl(n, alpha, s, 1)
     514            0 :           CALL dcopy_(n, x0, 1, x, 1)
     515            0 :           CALL daxpy_sl(n, one, s, 1, x, 1)
     516            0 :           mode = 1
     517            0 :           GO TO 330
     518            0 :   200         IF (h1.LE.h3/ten .OR. line.GT.10) GO TO 240
     519            0 :               alpha = MAX(h3/(two*(h3-h1)),alfmin)
     520            0 :               GO TO 190
     521              : 
     522              : !C   EXACT LINESEARCH
     523              : 
     524            0 :   210 IF (line.NE.3) THEN
     525            0 :           alpha = linmin(line,alfmin,one,t,tol)
     526            0 :           CALL dcopy_(n, x0, 1, x, 1)
     527            0 :           CALL daxpy_sl(n, alpha, s, 1, x, 1)
     528            0 :           mode = 1
     529            0 :           GOTO 330
     530              :       ENDIF
     531            0 :       CALL dscal_sl(n, alpha, s, 1)
     532            0 :       GOTO 240
     533              : 
     534              : !C   CALL FUNCTIONS AT CURRENT X
     535              : 
     536            0 :   220     t = f
     537            0 :           DO 230 j=1,m
     538            0 :              IF (j.LE.meq) THEN
     539            0 :                  h1 = c(j)
     540              :              ELSE
     541            0 :                  h1 = ZERO
     542              :              ENDIF
     543            0 :              t = t + mu(j)*MAX(-c(j),h1)
     544            0 :   230     CONTINUE
     545            0 :           h1 = t - t0
     546            0 :           GOTO (200, 210) iexact+1
     547              : 
     548              : !C   CHECK CONVERGENCE
     549              : 
     550            0 :   240 h3 = ZERO
     551            0 :       DO 250 j=1,m
     552            0 :          IF (j.LE.meq) THEN
     553            0 :              h1 = c(j)
     554              :          ELSE
     555            0 :              h1 = ZERO
     556              :          ENDIF
     557            0 :          h3 = h3 + MAX(-c(j),h1)
     558            0 :   250 CONTINUE
     559              :       IF ((ABS(f-f0).LT.acc .OR. dnrm2_(n,s,1).LT.acc) .AND. h3.LT.acc  &
     560            0 :            .AND. .NOT. badlin .AND. f .EQ. f) &
     561              :          THEN
     562            0 :             mode = 0
     563              :          ELSE
     564            0 :             mode = -1
     565              :          ENDIF
     566            0 :       GO TO 330
     567              : 
     568              : !C   CHECK relaxed CONVERGENCE in case of positive directional derivative
     569              : 
     570              :   255 CONTINUE
     571            0 :       h3 = ZERO
     572            0 :       DO 256 j=1,m
     573            0 :          IF (j.LE.meq) THEN
     574            0 :              h1 = c(j)
     575              :          ELSE
     576            0 :              h1 = ZERO
     577              :          ENDIF
     578            0 :          h3 = h3 + MAX(-c(j),h1)
     579            0 :   256 CONTINUE
     580              :       IF ((ABS(f-f0).LT.tol .OR. dnrm2_(n,s,1).LT.tol) .AND. h3.LT.tol  &
     581            0 :            .AND. .NOT. badlin .AND. f .EQ. f) &
     582              :          THEN
     583            0 :             mode = 0
     584              :          ELSE
     585            0 :             mode = 8
     586              :          ENDIF
     587            0 :       GO TO 330
     588              : 
     589              : !C   CALL JACOBIAN AT CURRENT X
     590              : 
     591              : !C   UPDATE CHOLESKY-FACTORS OF HESSIAN MATRIX BY MODIFIED BFGS FORMULA
     592              : 
     593            0 :   260 DO 270 i=1,n
     594            0 :          u(i) = g(i) - ddot_sl(m,a(1,i),1,r,1) - v(i)
     595            0 :   270 CONTINUE
     596              : 
     597              : !C   L'*S
     598              : 
     599              :       k = 0
     600            0 :       DO 290 i=1,n
     601            0 :          h1 = ZERO
     602            0 :          k = k + 1
     603            0 :          DO 280 j=i+1,n
     604            0 :             k = k + 1
     605            0 :             h1 = h1 + l(k)*s(j)
     606            0 :   280    CONTINUE
     607            0 :          v(i) = s(i) + h1
     608            0 :   290 CONTINUE
     609              : 
     610              : !C   D*L'*S
     611              : 
     612              :       k = 1
     613            0 :       DO 300 i=1,n
     614            0 :          v(i) = l(k)*v(i)
     615            0 :          k = k + n1 - i
     616            0 :   300 CONTINUE
     617              : 
     618              : !C   L*D*L'*S
     619              : 
     620            0 :       DO 320 i=n,1,-1
     621            0 :          h1 = ZERO
     622            0 :          k = i
     623            0 :          DO 310 j=1,i - 1
     624            0 :             h1 = h1 + l(k)*v(j)
     625            0 :             k = k + n - j
     626            0 :   310    CONTINUE
     627            0 :          v(i) = v(i) + h1
     628            0 :   320 CONTINUE
     629              : 
     630            0 :       h1 = ddot_sl(n,s,1,u,1)
     631            0 :       h2 = ddot_sl(n,s,1,v,1)
     632            0 :       h3 = 0.2d0*h2
     633            0 :       IF (h1.LT.h3) THEN
     634            0 :           h4 = (h2-h3)/(h2-h1)
     635            0 :           h1 = h3
     636            0 :           CALL dscal_sl(n, h4, u, 1)
     637            0 :           CALL daxpy_sl(n, one-h4, v, 1, u, 1)
     638              :       ENDIF
     639            0 :       IF (h1.EQ.0 .or. h2.EQ.0) THEN
     640              : !C         Singular update: reset hessian.
     641              :           GO TO 110
     642              :       end if
     643            0 :       CALL ldl(n, l, u, +one/h1, v)
     644            0 :       CALL ldl(n, l, v, -one/h2, u)
     645              : 
     646              : !C   END OF MAIN ITERATION
     647              : 
     648            0 :       GO TO 130
     649              : 
     650              : !C   END OF SLSQPB
     651              : 
     652              :   330 continue
     653            0 :       END SUBROUTINE slsqpb
     654              : 
     655              : 
     656            0 :       SUBROUTINE lsq(m,meq,n,nl,la,l,g,a,b,xl,xu,x,y,w,jw,mode)
     657              : 
     658              : !C   MINIMIZE with respect to X
     659              : 
     660              : !C             ||E*X - F||
     661              : !C                                      1/2  T
     662              : !C   WITH UPPER TRIANGULAR MATRIX E = +D   *L ,
     663              : 
     664              : !C                                      -1/2  -1
     665              : !C                     AND VECTOR F = -D    *L  *G,
     666              : 
     667              : !C  WHERE THE UNIT LOWER TRIDIANGULAR MATRIX L IS STORED COLUMNWISE
     668              : !C  DENSE IN THE N*(N+1)/2 ARRAY L WITH VECTOR D STORED IN ITS
     669              : !C 'DIAGONAL' THUS SUBSTITUTING THE ONE-ELEMENTS OF L
     670              : 
     671              : !C   SUBJECT TO
     672              : 
     673              : !C             A(J)*X - B(J) = 0 ,         J=1,...,MEQ,
     674              : !C             A(J)*X - B(J) >=0,          J=MEQ+1,...,M,
     675              : !C             XL(I) <= X(I) <= XU(I),     I=1,...,N,
     676              : !C     ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS L, G, A, B, XL, XU.
     677              : !C     WITH DIMENSIONS: L(N*(N+1)/2), G(N), A(LA,N), B(M), XL(N), XU(N)
     678              : !C     THE WORKING ARRAY W MUST HAVE AT LEAST THE FOLLOWING DIMENSION:
     679              : !c     DIM(W) =        (3*N+M)*(N+1)                        for LSQ
     680              : !c                    +(N-MEQ+1)*(MINEQ+2) + 2*MINEQ        for LSI
     681              : !c                    +(N+MINEQ)*(N-MEQ) + 2*MEQ + N        for LSEI
     682              : !c                      with MINEQ = M - MEQ + 2*N
     683              : !C     ON RETURN, NO ARRAY WILL BE CHANGED BY THE SUBROUTINE.
     684              : !C     X     STORES THE N-DIMENSIONAL SOLUTION VECTOR
     685              : !C     Y     STORES THE VECTOR OF LAGRANGE MULTIPLIERS OF DIMENSION
     686              : !C           M+N+N (CONSTRAINTS+LOWER+UPPER BOUNDS)
     687              : !C     MODE  IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS:
     688              : !C          MODE=1: SUCCESSFUL COMPUTATION
     689              : !C               2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1)
     690              : !C               3: ITERATION COUNT EXCEEDED BY NNLS
     691              : !C               4: INEQUALITY CONSTRAINTS INCOMPATIBLE
     692              : !C               5: MATRIX E IS NOT OF FULL RANK
     693              : !C               6: MATRIX C IS NOT OF FULL RANK
     694              : !C               7: RANK DEFECT IN HFTI
     695              : 
     696              : !c     coded            Dieter Kraft, april 1987
     697              : !c     revised                        march 1989
     698              : 
     699              :       DOUBLE PRECISION l,g,a,b,w,xl,xu,x,y, &
     700              :                        diag,ZERO,one,xnorm
     701              : 
     702              :       INTEGER          jw(*),i,ic,id,ie,IF,ig,ih,il,ip,iw,&
     703              :            i1,i2,i3,i4,la,m,meq,mineq,mode,m1,n,nl,n1,n2,n3,&
     704              :            nancnt,j
     705              : 
     706              :       DIMENSION        a(la,n), b(la), g(n), l(nl),&
     707              :                        w(*), x(n), xl(n), xu(n), y(m+n+n)
     708              : 
     709              :       DATA             ZERO/0.0d0/, one/1.0d0/
     710              : 
     711            0 :       n1 = n + 1
     712            0 :       mineq = m - meq
     713            0 :       m1 = mineq + n + n
     714              : 
     715              : !c  determine whether to solve problem
     716              : !c  with inconsistent linerarization (n2=1)
     717              : !c  or not (n2=0)
     718              : 
     719            0 :       n2 = n1*n/2 + 1
     720            0 :       IF (n2.EQ.nl) THEN
     721              :           n2 = 0
     722              :       ELSE
     723            0 :           n2 = 1
     724              :       ENDIF
     725            0 :       n3 = n-n2
     726              : 
     727              : !C  RECOVER MATRIX E AND VECTOR F FROM L AND G
     728              : 
     729            0 :       i2 = 1
     730            0 :       i3 = 1
     731            0 :       i4 = 1
     732            0 :       ie = 1
     733            0 :       IF = n*n+1
     734            0 :       DO 10 i=1,n3
     735            0 :          i1 = n1-i
     736            0 :          diag = SQRT (l(i2))
     737            0 :          w(i3) = ZERO
     738            0 :          CALL dcopy_ (i1  ,  w(i3), 0, w(i3), 1)
     739            0 :          CALL dcopy_ (i1-n2, l(i2), 1, w(i3), n)
     740            0 :          CALL dscal_sl (i1-n2,     diag, w(i3), n)
     741            0 :          w(i3) = diag
     742            0 :          w(IF-1+i) = (g(i) - ddot_sl (i-1, w(i4), 1, w(IF), 1))/diag
     743            0 :          i2 = i2 + i1 - n2
     744            0 :          i3 = i3 + n1
     745            0 :          i4 = i4 + n
     746            0 :    10 CONTINUE
     747            0 :       IF (n2.EQ.1) THEN
     748            0 :           w(i3) = l(nl)
     749            0 :           w(i4) = ZERO
     750            0 :           CALL dcopy_ (n3, w(i4), 0, w(i4), 1)
     751            0 :           w(IF-1+n) = ZERO
     752              :       ENDIF
     753            0 :       CALL dscal_sl (n, - one, w(IF), 1)
     754              : 
     755            0 :       ic = IF + n
     756            0 :       id = ic + meq*n
     757              : 
     758            0 :       IF (meq .GT. 0) THEN
     759              : 
     760              : !C  RECOVER MATRIX C FROM UPPER PART OF A
     761              : 
     762            0 :           DO 20 i=1,meq
     763            0 :               CALL dcopy_ (n, a(i,1), la, w(ic-1+i), meq)
     764            0 :    20     CONTINUE
     765              : 
     766              : !C  RECOVER VECTOR D FROM UPPER PART OF B
     767              : 
     768            0 :           CALL dcopy_ (meq, b(1), 1, w(id), 1)
     769            0 :           CALL dscal_sl (meq,   - one, w(id), 1)
     770              : 
     771              :       ENDIF
     772              : 
     773            0 :       ig = id + meq
     774              : 
     775              : !C  RECOVER MATRIX G FROM LOWER PART OF A
     776              : !C  The matrix G(mineq+2*n,m1) is stored at w(ig)
     777              : !C  Not all rows will be filled if some of the upper/lower
     778              : !C  bounds are unbounded.
     779              : 
     780            0 :       IF (mineq .GT. 0) THEN
     781              : 
     782            0 :           DO 30 i=1,mineq
     783            0 :               CALL dcopy_ (n, a(meq+i,1), la, w(ig-1+i), m1)
     784            0 :    30     CONTINUE
     785              : 
     786              :       ENDIF
     787              : 
     788            0 :       ih = ig + m1*n
     789            0 :       iw = ih + mineq + 2*n
     790              : 
     791            0 :       IF (mineq .GT. 0) THEN
     792              : 
     793              : !C  RECOVER H FROM LOWER PART OF B
     794              : !C  The vector H(mineq+2*n) is stored at w(ih)
     795              : 
     796            0 :           CALL dcopy_ (mineq, b(meq+1), 1, w(ih), 1)
     797            0 :           CALL dscal_sl (mineq,       - one, w(ih), 1)
     798              : 
     799              :       ENDIF
     800              : 
     801              : !C  AUGMENT MATRIX G BY +I AND -I, AND,
     802              : !C  AUGMENT VECTOR H BY XL AND XU
     803              : !C  NaN value indicates no bound
     804              : 
     805            0 :       ip = ig + mineq
     806            0 :       il = ih + mineq
     807            0 :       nancnt = 0
     808              : 
     809            0 :       DO 40 i=1,n
     810            0 :          if (xl(i).eq.xl(i)) then
     811            0 :             w(il) = xl(i)
     812            0 :             do 41 j=1,n
     813            0 :                w(ip + m1*(j-1)) = 0
     814            0 :  41         continue
     815            0 :             w(ip + m1*(i-1)) = 1
     816            0 :             ip = ip + 1
     817            0 :             il = il + 1
     818              :          else
     819            0 :             nancnt = nancnt + 1
     820              :          end if
     821            0 :    40 CONTINUE
     822              : 
     823            0 :       DO 50 i=1,n
     824            0 :          if (xu(i).eq.xu(i)) then
     825            0 :             w(il) = -xu(i)
     826            0 :             do 51 j=1,n
     827            0 :                w(ip + m1*(j-1)) = 0
     828            0 :  51         continue
     829            0 :             w(ip + m1*(i-1)) = -1
     830            0 :             ip = ip + 1
     831            0 :             il = il + 1
     832              :          else
     833            0 :             nancnt = nancnt + 1
     834              :          end if
     835            0 :  50   CONTINUE
     836              : 
     837              :       CALL lsei (w(ic), w(id), w(ie), w(IF), w(ig), w(ih), MAX(1,meq),&
     838            0 :                  meq, n, n, m1, m1-nancnt, n, x, xnorm, w(iw), jw, mode)
     839              : 
     840            0 :       IF (mode .EQ. 1) THEN
     841              : 
     842              : !c   restore Lagrange multipliers (only for user-defined variables)
     843              : 
     844            0 :           CALL dcopy_ (m,  w(iw),     1, y(1),      1)
     845              : 
     846              : !c   set rest of the multipliers to nan (they are not used)
     847              : 
     848            0 :           IF (n3 .GT. 0) THEN
     849            0 :              y(m+1) = 0
     850            0 :              y(m+1) = 0 / y(m+1)
     851            0 :              do 60 i=m+2,m+n3+n3
     852            0 :                 y(i) = y(m+1)
     853            0 :  60          continue
     854              :           ENDIF
     855              : 
     856              :       ENDIF
     857            0 :       call bound(n, x, xl, xu)
     858              : 
     859              : !C   END OF SUBROUTINE LSQ
     860              : 
     861            0 :       END SUBROUTINE lsq
     862              : 
     863              : 
     864            0 :       SUBROUTINE lsei(c,d,e,f,g,h,lc,mc,LE,me,lg,mg,n,x,xnrm,w,jw,mode)
     865              : 
     866              : !C     FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF
     867              : !C     EQUALITY & INEQUALITY CONSTRAINED LEAST SQUARES PROBLEM LSEI :
     868              : 
     869              : !C                MIN ||E*X - F||
     870              : !C                 X
     871              : 
     872              : !C                S.T.  C*X  = D,
     873              : !C                      G*X >= H.
     874              : 
     875              : !C     USING QR DECOMPOSITION & ORTHOGONAL BASIS OF NULLSPACE OF C
     876              : !C     CHAPTER 23.6 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS.
     877              : 
     878              : !C     THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM
     879              : !C     ARE NECESSARY
     880              : !C     DIM(E) :   FORMAL (LE,N),    ACTUAL (ME,N)
     881              : !C     DIM(F) :   FORMAL (LE  ),    ACTUAL (ME  )
     882              : !C     DIM(C) :   FORMAL (LC,N),    ACTUAL (MC,N)
     883              : !C     DIM(D) :   FORMAL (LC  ),    ACTUAL (MC  )
     884              : !C     DIM(G) :   FORMAL (LG,N),    ACTUAL (MG,N)
     885              : !C     DIM(H) :   FORMAL (LG  ),    ACTUAL (MG  )
     886              : !C     DIM(X) :   FORMAL (N   ),    ACTUAL (N   )
     887              : !C     DIM(W) :   2*MC+ME+(ME+MG)*(N-MC)  for LSEI
     888              : !C              +(N-MC+1)*(MG+2)+2*MG     for LSI
     889              : !C     DIM(JW):   MAX(MG,L)
     890              : !C     ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS C, D, E, F, G, AND H.
     891              : !C     ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE.
     892              : !C     X     STORES THE SOLUTION VECTOR
     893              : !C     XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM
     894              : !C     W     STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST
     895              : !C           MC+MG ELEMENTS
     896              : !C     MODE  IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS:
     897              : !C          MODE=1: SUCCESSFUL COMPUTATION
     898              : !C               2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1)
     899              : !C               3: ITERATION COUNT EXCEEDED BY NNLS
     900              : !C               4: INEQUALITY CONSTRAINTS INCOMPATIBLE
     901              : !C               5: MATRIX E IS NOT OF FULL RANK
     902              : !C               6: MATRIX C IS NOT OF FULL RANK
     903              : !C               7: RANK DEFECT IN HFTI
     904              : 
     905              : !C     18.5.1981, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN
     906              : !C     20.3.1987, DIETER KRAFT, DFVLR OBERPFAFFENHOFEN
     907              : 
     908              :       INTEGER          jw(*),i,ie,IF,ig,iw,j,k,krank,l,lc,LE,lg,&
     909              :                        mc,mc1,me,mg,mode,n
     910              :       DOUBLE PRECISION c(lc,n),e(LE,n),g(lg,n),d(lc),f(LE),h(lg),x(n),&
     911              :                        w(*),t,xnrm,rnorm(1),epmach,ZERO
     912              :       DATA             epmach/2.22d-16/,ZERO/0.0d+00/
     913              : 
     914            0 :       mode=2
     915            0 :       IF(mc.GT.n)                      GOTO 75
     916            0 :       l=n-mc
     917            0 :       mc1=mc+1
     918            0 :       iw=(l+1)*(mg+2)+2*mg+mc
     919            0 :       ie=iw+mc+1
     920            0 :       IF=ie+me*l
     921            0 :       ig=IF+me
     922              : 
     923              : !C  TRIANGULARIZE C AND APPLY FACTORS TO E AND G
     924              : 
     925            0 :       DO 10 i=1,mc
     926            0 :           j=MIN(i+1,lc)
     927            0 :           CALL h12(1,i,i+1,n,c(i,1),lc,w(iw+i),c(j,1),lc,1,mc-i)
     928            0 :           CALL h12(2,i,i+1,n,c(i,1),lc,w(iw+i),e     ,LE,1,me)
     929            0 :           CALL h12(2,i,i+1,n,c(i,1),lc,w(iw+i),g     ,lg,1,mg)
     930            0 :    10 CONTINUE
     931              : 
     932              : !C  SOLVE C*X=D AND MODIFY F
     933              : 
     934            0 :       mode=6
     935            0 :       DO 15 i=1,mc
     936            0 :           IF(ABS(c(i,i)).LT.epmach)    GOTO 75
     937            0 :           x(i)=(d(i)-ddot_sl(i-1,c(i,1),lc,x,1))/c(i,i)
     938            0 :    15 CONTINUE
     939            0 :       mode=1
     940            0 :       w(mc1) = ZERO
     941            0 :       CALL dcopy_ (mg-mc,w(mc1),0,w(mc1),1)
     942              : 
     943            0 :       IF(mc.EQ.n)                      GOTO 50
     944              : 
     945            0 :       DO 20 i=1,me
     946            0 :           w(IF-1+i)=f(i)-ddot_sl(mc,e(i,1),LE,x,1)
     947            0 :    20 CONTINUE
     948              : !C  STORE TRANSFORMED E & G
     949              : 
     950            0 :       DO 25 i=1,me
     951            0 :           CALL dcopy_(l,e(i,mc1),LE,w(ie-1+i),me)
     952            0 :    25 CONTINUE
     953            0 :       DO 30 i=1,mg
     954            0 :           CALL dcopy_(l,g(i,mc1),lg,w(ig-1+i),mg)
     955            0 :    30 CONTINUE
     956              : 
     957            0 :       IF(mg.GT.0)                      GOTO 40
     958              : 
     959              : !C  SOLVE LS WITHOUT INEQUALITY CONSTRAINTS
     960              : 
     961            0 :       mode=7
     962            0 :       k=MAX(LE,n)
     963            0 :       t=SQRT(epmach)
     964            0 :       CALL hfti (w(ie),me,me,l,w(IF),k,1,t,krank,rnorm,w,w(l+1),jw)
     965              : !C  HFTI IS MORE GENERIC, BUT WE ONLY CALL IT WITH NB=1, SO RETRIEVE THE
     966              : !C  SINGLE VALUE WE NEED FROM RNORM HERE
     967            0 :       xnrm = rnorm(1)
     968            0 :       CALL dcopy_(l,w(IF),1,x(mc1),1)
     969            0 :       IF(krank.NE.l)                   GOTO 75
     970            0 :       mode=1
     971            0 :                                        GOTO 50
     972              : !C  MODIFY H AND SOLVE INEQUALITY CONSTRAINED LS PROBLEM
     973              : 
     974            0 :    40 DO 45 i=1,mg
     975            0 :           h(i)=h(i)-ddot_sl(mc,g(i,1),lg,x,1)
     976            0 :    45 CONTINUE
     977              :       CALL lsi &
     978            0 :        (w(ie),w(IF),w(ig),h,me,me,mg,mg,l,x(mc1),xnrm,w(mc1),jw,mode)
     979            0 :       IF(mc.EQ.0)                      GOTO 75
     980            0 :       t=dnrm2_(mc,x,1)
     981            0 :       xnrm=SQRT(xnrm*xnrm+t*t)
     982            0 :       IF(mode.NE.1)                    GOTO 75
     983              : 
     984              : !C  SOLUTION OF ORIGINAL PROBLEM AND LAGRANGE MULTIPLIERS
     985              : 
     986            0 :    50 DO 55 i=1,me
     987            0 :           f(i)=ddot_sl(n,e(i,1),LE,x,1)-f(i)
     988            0 :    55 CONTINUE
     989            0 :       DO 60 i=1,mc
     990            0 :           d(i)=ddot_sl(me,e(1,i),1,f,1)-ddot_sl(mg,g(1,i),1,w(mc1),1)
     991            0 :    60 CONTINUE
     992            0 :       DO 65 i=mc,1,-1
     993            0 :           CALL h12(2,i,i+1,n,c(i,1),lc,w(iw+i),x,1,1,1)
     994            0 :    65 CONTINUE
     995            0 :       DO 70 i=mc,1,-1
     996            0 :           j=MIN(i+1,lc)
     997            0 :           w(i)=(d(i)-ddot_sl(mc-i,c(j,i),1,w(j),1))/c(i,i)
     998            0 :    70 CONTINUE
     999              : 
    1000              : !C  END OF SUBROUTINE LSEI
    1001              : 
    1002              :    75 CONTINUE
    1003              : 
    1004            0 :       END SUBROUTINE lsei
    1005              : 
    1006            0 :       SUBROUTINE lsi(e,f,g,h,LE,me,lg,mg,n,x,xnorm,w,jw,mode)
    1007              : 
    1008              : !C     FOR MODE=1, THE SUBROUTINE RETURNS THE SOLUTION X OF
    1009              : !C     INEQUALITY CONSTRAINED LINEAR LEAST SQUARES PROBLEM:
    1010              : 
    1011              : !C                    MIN ||E*X-F||
    1012              : !C                     X
    1013              : 
    1014              : !C                    S.T.  G*X >= H
    1015              : 
    1016              : !C     THE ALGORITHM IS BASED ON QR DECOMPOSITION AS DESCRIBED IN
    1017              : !C     CHAPTER 23.5 OF LAWSON & HANSON: SOLVING LEAST SQUARES PROBLEMS
    1018              : 
    1019              : !C     THE FOLLOWING DIMENSIONS OF THE ARRAYS DEFINING THE PROBLEM
    1020              : !C     ARE NECESSARY
    1021              : !C     DIM(E) :   FORMAL (LE,N),    ACTUAL (ME,N)
    1022              : !C     DIM(F) :   FORMAL (LE  ),    ACTUAL (ME  )
    1023              : !C     DIM(G) :   FORMAL (LG,N),    ACTUAL (MG,N)
    1024              : !C     DIM(H) :   FORMAL (LG  ),    ACTUAL (MG  )
    1025              : !C     DIM(X) :   N
    1026              : !C     DIM(W) :   (N+1)*(MG+2) + 2*MG
    1027              : !C     DIM(JW):   LG
    1028              : !C     ON ENTRY, THE USER HAS TO PROVIDE THE ARRAYS E, F, G, AND H.
    1029              : !C     ON RETURN, ALL ARRAYS WILL BE CHANGED BY THE SUBROUTINE.
    1030              : !C     X     STORES THE SOLUTION VECTOR
    1031              : !C     XNORM STORES THE RESIDUUM OF THE SOLUTION IN EUCLIDIAN NORM
    1032              : !C     W     STORES THE VECTOR OF LAGRANGE MULTIPLIERS IN ITS FIRST
    1033              : !C           MG ELEMENTS
    1034              : !C     MODE  IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANINGS:
    1035              : !C          MODE=1: SUCCESSFUL COMPUTATION
    1036              : !C               2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N<1)
    1037              : !C               3: ITERATION COUNT EXCEEDED BY NNLS
    1038              : !C               4: INEQUALITY CONSTRAINTS INCOMPATIBLE
    1039              : !C               5: MATRIX E IS NOT OF FULL RANK
    1040              : 
    1041              : !C     03.01.1980, DIETER KRAFT: CODED
    1042              : !C     20.03.1987, DIETER KRAFT: REVISED TO FORTRAN 77
    1043              : 
    1044              :       INTEGER          i,j,LE,lg,me,mg,mode,n,jw(lg)
    1045              :       DOUBLE PRECISION e(LE,n),f(LE),g(lg,n),h(lg),x(n),w(*),&
    1046              :                        xnorm,epmach,t,one
    1047              :       DATA             epmach/2.22d-16/,one/1.0d+00/
    1048              : 
    1049              : !C  QR-FACTORS OF E AND APPLICATION TO F
    1050              : 
    1051            0 :       DO 10 i=1,n
    1052            0 :       j=MIN(i+1,n)
    1053            0 :       CALL h12(1,i,i+1,me,e(1,i),1,t,e(1,j),1,LE,n-i)
    1054            0 :       CALL h12(2,i,i+1,me,e(1,i),1,t,f     ,1,1 ,1  )
    1055            0 :    10 CONTINUE
    1056              : !C  TRANSFORM G AND H TO GET LEAST DISTANCE PROBLEM
    1057              : 
    1058            0 :       mode=5
    1059            0 :       DO 30 i=1,mg
    1060            0 :           DO 20 j=1,n
    1061            0 :               IF (.NOT.(ABS(e(j,j)).GE.epmach)) GOTO 50
    1062            0 :               g(i,j)=(g(i,j)-ddot_sl(j-1,g(i,1),lg,e(1,j),1))/e(j,j)
    1063            0 :    20     CONTINUE
    1064            0 :           h(i)=h(i)-ddot_sl(n,g(i,1),lg,f,1)
    1065            0 :    30 CONTINUE
    1066              : 
    1067              : !C  SOLVE LEAST DISTANCE PROBLEM
    1068              : 
    1069            0 :       CALL ldp(g,lg,mg,n,h,x,xnorm,w,jw,mode)
    1070            0 :       IF (mode.NE.1)                     GOTO 50
    1071              : 
    1072              : !C  SOLUTION OF ORIGINAL PROBLEM
    1073              : 
    1074            0 :       CALL daxpy_sl(n,one,f,1,x,1)
    1075            0 :       DO 40 i=n,1,-1
    1076            0 :           j=MIN(i+1,n)
    1077            0 :           x(i)=(x(i)-ddot_sl(n-i,e(i,j),LE,x(j),1))/e(i,i)
    1078            0 :    40 CONTINUE
    1079            0 :       j=MIN(n+1,me)
    1080            0 :       t=dnrm2_(me-n,f(j),1)
    1081            0 :       xnorm=SQRT(xnorm*xnorm+t*t)
    1082              : 
    1083              : !C  END OF SUBROUTINE LSI
    1084              : 
    1085              :    50 CONTINUE
    1086              : 
    1087            0 :       END SUBROUTINE lsi
    1088              : 
    1089            0 :       SUBROUTINE ldp(g,mg,m,n,h,x,xnorm,w,INDEX,mode)
    1090              : 
    1091              : !C                     T
    1092              : !C     MINIMIZE   1/2 X X    SUBJECT TO   G * X >= H.
    1093              : 
    1094              : !C       C.L. LAWSON, R.J. HANSON: 'SOLVING LEAST SQUARES PROBLEMS'
    1095              : !C       PRENTICE HALL, ENGLEWOOD CLIFFS, NEW JERSEY, 1974.
    1096              : 
    1097              : !C     PARAMETER DESCRIPTION:
    1098              : 
    1099              : !C     G(),MG,M,N   ON ENTRY G() STORES THE M BY N MATRIX OF
    1100              : !C                  LINEAR INEQUALITY CONSTRAINTS. G() HAS FIRST
    1101              : !C                  DIMENSIONING PARAMETER MG
    1102              : !C     H()          ON ENTRY H() STORES THE M VECTOR H REPRESENTING
    1103              : !C                  THE RIGHT SIDE OF THE INEQUALITY SYSTEM
    1104              : 
    1105              : !C     REMARK: G(),H() WILL NOT BE CHANGED DURING CALCULATIONS BY LDP
    1106              : 
    1107              : !C     X()          ON ENTRY X() NEED NOT BE INITIALIZED.
    1108              : !C                  ON EXIT X() STORES THE SOLUTION VECTOR X IF MODE=1.
    1109              : !C     XNORM        ON EXIT XNORM STORES THE EUCLIDIAN NORM OF THE
    1110              : !C                  SOLUTION VECTOR IF COMPUTATION IS SUCCESSFUL
    1111              : !C     W()          W IS A ONE DIMENSIONAL WORKING SPACE, THE LENGTH
    1112              : !C                  OF WHICH SHOULD BE AT LEAST (M+2)*(N+1) + 2*M
    1113              : !C                  ON EXIT W() STORES THE LAGRANGE MULTIPLIERS
    1114              : !C                  ASSOCIATED WITH THE CONSTRAINTS
    1115              : !C                  AT THE SOLUTION OF PROBLEM LDP
    1116              : !C     INDEX()      INDEX() IS A ONE DIMENSIONAL INTEGER WORKING SPACE
    1117              : !C                  OF LENGTH AT LEAST M
    1118              : !C     MODE         MODE IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING
    1119              : !C                  MEANINGS:
    1120              : !C          MODE=1: SUCCESSFUL COMPUTATION
    1121              : !C               2: ERROR RETURN BECAUSE OF WRONG DIMENSIONS (N.LE.0)
    1122              : !C               3: ITERATION COUNT EXCEEDED BY NNLS
    1123              : !C               4: INEQUALITY CONSTRAINTS INCOMPATIBLE
    1124              : 
    1125              :       DOUBLE PRECISION g,h,x,xnorm,w,u,v,&
    1126              :                        ZERO,one,fac,rnorm,diff
    1127              :       INTEGER          INDEX,i,IF,iw,iwdual,iy,iz,j,m,mg,mode,n,n1
    1128              :       DIMENSION        g(mg,n),h(m),x(n),w(*),INDEX(m)
    1129              :       diff(u,v)=       u-v
    1130              :       DATA             ZERO,one/0.0d0,1.0d0/
    1131              : 
    1132            0 :       mode=2
    1133            0 :       IF(n.LE.0)                    GOTO 50
    1134              : 
    1135              : !C  STATE DUAL PROBLEM
    1136              : 
    1137            0 :       mode=1
    1138            0 :       x(1)=ZERO
    1139            0 :       CALL dcopy_(n,x(1),0,x,1)
    1140            0 :       xnorm=ZERO
    1141            0 :       IF(m.EQ.0)                    GOTO 50
    1142              :       iw=0
    1143            0 :       DO 20 j=1,m
    1144            0 :           DO 10 i=1,n
    1145            0 :               iw=iw+1
    1146            0 :               w(iw)=g(j,i)
    1147            0 :    10     CONTINUE
    1148            0 :           iw=iw+1
    1149            0 :           w(iw)=h(j)
    1150            0 :    20 CONTINUE
    1151              :       IF=iw+1
    1152            0 :       DO 30 i=1,n
    1153            0 :           iw=iw+1
    1154            0 :           w(iw)=ZERO
    1155            0 :    30 CONTINUE
    1156            0 :       w(iw+1)=one
    1157            0 :       n1=n+1
    1158            0 :       iz=iw+2
    1159            0 :       iy=iz+n1
    1160            0 :       iwdual=iy+m
    1161              : 
    1162              : !C  SOLVE DUAL PROBLEM
    1163              : 
    1164            0 :       CALL nnls (w,n1,n1,m,w(IF),w(iy),rnorm,w(iwdual),w(iz),INDEX,mode)
    1165              : 
    1166            0 :       IF(mode.NE.1)                 GOTO 50
    1167            0 :       mode=4
    1168            0 :       IF(rnorm.LE.ZERO)             GOTO 50
    1169              : 
    1170              : !C  COMPUTE SOLUTION OF PRIMAL PROBLEM
    1171              : 
    1172            0 :       fac=one-ddot_sl(m,h,1,w(iy),1)
    1173            0 :       IF(.NOT.(diff(one+fac,one).GT.ZERO)) GOTO 50
    1174            0 :       mode=1
    1175            0 :       fac=one/fac
    1176            0 :       DO 40 j=1,n
    1177            0 :           x(j)=fac*ddot_sl(m,g(1,j),1,w(iy),1)
    1178            0 :    40 CONTINUE
    1179            0 :       xnorm=dnrm2_(n,x,1)
    1180              : 
    1181              : !C  COMPUTE LAGRANGE MULTIPLIERS FOR PRIMAL PROBLEM
    1182              : 
    1183            0 :       w(1)=ZERO
    1184            0 :       CALL dcopy_(m,w(1),0,w,1)
    1185            0 :       CALL daxpy_sl(m,fac,w(iy),1,w,1)
    1186              : 
    1187              : !C  END OF SUBROUTINE LDP
    1188              : 
    1189              :    50 CONTINUE
    1190              : 
    1191            0 :       END SUBROUTINE ldp
    1192              : 
    1193              : 
    1194            0 :       SUBROUTINE nnls (a, mda, m, n, b, x, rnorm, w, z, INDEX, mode)
    1195              : 
    1196              : !C     C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY:
    1197              : !C     'SOLVING LEAST SQUARES PROBLEMS'. PRENTICE-HALL.1974
    1198              : 
    1199              : !C      **********   NONNEGATIVE LEAST SQUARES   **********
    1200              : 
    1201              : !C     GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN
    1202              : !C     N-VECTOR, X, WHICH SOLVES THE LEAST SQUARES PROBLEM
    1203              : 
    1204              : !C                  A*X = B  SUBJECT TO  X >= 0
    1205              : 
    1206              : !C     A(),MDA,M,N
    1207              : !C            MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE ARRAY,A().
    1208              : !C            ON ENTRY A()  CONTAINS THE M BY N MATRIX,A.
    1209              : !C            ON EXIT A() CONTAINS THE PRODUCT Q*A,
    1210              : !C            WHERE Q IS AN M BY M ORTHOGONAL MATRIX GENERATED
    1211              : !C            IMPLICITLY BY THIS SUBROUTINE.
    1212              : !C            EITHER M>=N OR M<N IS PERMISSIBLE.
    1213              : !C            THERE IS NO RESTRICTION ON THE RANK OF A.
    1214              : !C     B()    ON ENTRY B() CONTAINS THE M-VECTOR, B.
    1215              : !C            ON EXIT B() CONTAINS Q*B.
    1216              : !C     X()    ON ENTRY X() NEED NOT BE INITIALIZED.
    1217              : !C            ON EXIT X() WILL CONTAIN THE SOLUTION VECTOR.
    1218              : !C     RNORM  ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE
    1219              : !C            RESIDUAL VECTOR.
    1220              : !C     W()    AN N-ARRAY OF WORKING SPACE.
    1221              : !C            ON EXIT W() WILL CONTAIN THE DUAL SOLUTION VECTOR.
    1222              : !C            W WILL SATISFY W(I)=0 FOR ALL I IN SET P
    1223              : !C            AND W(I)<=0 FOR ALL I IN SET Z
    1224              : !C     Z()    AN M-ARRAY OF WORKING SPACE.
    1225              : !C     INDEX()AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N.
    1226              : !C            ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS
    1227              : !C            P AND Z AS FOLLOWS:
    1228              : !C            INDEX(1)    THRU INDEX(NSETP) = SET P.
    1229              : !C            INDEX(IZ1)  THRU INDEX (IZ2)  = SET Z.
    1230              : !C            IZ1=NSETP + 1 = NPP1, IZ2=N.
    1231              : !C     MODE   THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING MEANING:
    1232              : !C            1    THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY.
    1233              : !C            2    THE DIMENSIONS OF THE PROBLEM ARE WRONG,
    1234              : !C                 EITHER M <= 0 OR N <= 0.
    1235              : !C            3    ITERATION COUNT EXCEEDED, MORE THAN 3*N ITERATIONS.
    1236              : 
    1237              :       INTEGER          i,ii,ip,iter,itmax,iz,izmax,iz1,iz2,j,jj,jz,&
    1238              :                        k,l,m,mda,mode,n,npp1,nsetp,INDEX(n)
    1239              : 
    1240              :       DOUBLE PRECISION a(mda,n),b(m),x(n),w(n),z(m),asave,diff,&
    1241              :                        factor,ZERO,one,wmax,alpha,&
    1242              :                        c,s,t,u,v,up,rnorm,unorm
    1243              : 
    1244              :       diff(u,v)=       u-v
    1245              : 
    1246              :       DATA             ZERO,one,factor/0.0d0,1.0d0,1.0d-2/
    1247              : 
    1248              : !c     revised          Dieter Kraft, March 1983
    1249              : 
    1250            0 :       mode=2
    1251            0 :       IF(m.LE.0.OR.n.LE.0)            GOTO 290
    1252            0 :       mode=1
    1253            0 :       iter=0
    1254            0 :       itmax=3*n
    1255              : 
    1256              : !C STEP ONE (INITIALIZE)
    1257              : 
    1258            0 :       DO 100 i=1,n
    1259            0 :          INDEX(i)=i
    1260            0 :   100 CONTINUE
    1261            0 :       iz1=1
    1262            0 :       iz2=n
    1263            0 :       nsetp=0
    1264            0 :       npp1=1
    1265            0 :       x(1)=ZERO
    1266            0 :       CALL dcopy_(n,x(1),0,x,1)
    1267              : 
    1268              : !C STEP TWO (COMPUTE DUAL VARIABLES)
    1269              : !C .....ENTRY LOOP A
    1270              : 
    1271            0 :   110 IF(iz1.GT.iz2.OR.nsetp.GE.m)    GOTO 280
    1272            0 :       DO 120 iz=iz1,iz2
    1273            0 :          j=INDEX(iz)
    1274            0 :          w(j)=ddot_sl(m-nsetp,a(npp1,j),1,b(npp1),1)
    1275            0 :   120 CONTINUE
    1276              : 
    1277              : !C STEP THREE (TEST DUAL VARIABLES)
    1278              : 
    1279            0 :   130 wmax=ZERO
    1280            0 :       DO 140 iz=iz1,iz2
    1281            0 :       j=INDEX(iz)
    1282            0 :          IF(w(j).LE.wmax)             GOTO 140
    1283            0 :          wmax=w(j)
    1284            0 :          izmax=iz
    1285            0 :   140 CONTINUE
    1286              : 
    1287              : !C .....EXIT LOOP A
    1288              : 
    1289            0 :       IF(wmax.LE.ZERO)                GOTO 280
    1290            0 :       iz=izmax
    1291            0 :       j=INDEX(iz)
    1292              : 
    1293              : !C STEP FOUR (TEST INDEX J FOR LINEAR DEPENDENCY)
    1294              : 
    1295            0 :       asave=a(npp1,j)
    1296            0 :       CALL h12(1,npp1,npp1+1,m,a(1,j),1,up,z,1,1,0)
    1297            0 :       unorm=dnrm2_(nsetp,a(1,j),1)
    1298            0 :       t=factor*ABS(a(npp1,j))
    1299            0 :       IF(diff(unorm+t,unorm).LE.ZERO) GOTO 150
    1300            0 :       CALL dcopy_(m,b,1,z,1)
    1301            0 :       CALL h12(2,npp1,npp1+1,m,a(1,j),1,up,z,1,1,1)
    1302            0 :       IF(z(npp1)/a(npp1,j).GT.ZERO)   GOTO 160
    1303            0 :   150 a(npp1,j)=asave
    1304            0 :       w(j)=ZERO
    1305            0 :                                       GOTO 130
    1306              : !C STEP FIVE (ADD COLUMN)
    1307              : 
    1308            0 :   160 CALL dcopy_(m,z,1,b,1)
    1309            0 :       INDEX(iz)=INDEX(iz1)
    1310            0 :       INDEX(iz1)=j
    1311            0 :       iz1=iz1+1
    1312            0 :       nsetp=npp1
    1313            0 :       npp1=npp1+1
    1314            0 :       DO 170 jz=iz1,iz2
    1315            0 :          jj=INDEX(jz)
    1316            0 :          CALL h12(2,nsetp,npp1,m,a(1,j),1,up,a(1,jj),1,mda,1)
    1317            0 :   170 CONTINUE
    1318            0 :       k=MIN(npp1,mda)
    1319            0 :       w(j)=ZERO
    1320            0 :       CALL dcopy_(m-nsetp,w(j),0,a(k,j),1)
    1321              : 
    1322              : !C STEP SIX (SOLVE LEAST SQUARES SUB-PROBLEM)
    1323              : !C .....ENTRY LOOP B
    1324              : 
    1325            0 :   180 DO 200 ip=nsetp,1,-1
    1326            0 :          IF(ip.EQ.nsetp)              GOTO 190
    1327            0 :          CALL daxpy_sl(ip,-z(ip+1),a(1,jj),1,z,1)
    1328            0 :   190    jj=INDEX(ip)
    1329            0 :          z(ip)=z(ip)/a(ip,jj)
    1330            0 :   200 CONTINUE
    1331            0 :       iter=iter+1
    1332            0 :       IF(iter.LE.itmax)               GOTO 220
    1333            0 :   210 mode=3
    1334            0 :                                       GOTO 280
    1335              : !C STEP SEVEN TO TEN (STEP LENGTH ALGORITHM)
    1336              : 
    1337            0 :   220 alpha=one
    1338            0 :       jj=0
    1339            0 :       DO 230 ip=1,nsetp
    1340            0 :          IF(z(ip).GT.ZERO)            GOTO 230
    1341            0 :          l=INDEX(ip)
    1342            0 :          t=-x(l)/(z(ip)-x(l))
    1343            0 :          IF(alpha.LT.t)               GOTO 230
    1344            0 :          alpha=t
    1345            0 :          jj=ip
    1346            0 :   230 CONTINUE
    1347            0 :       DO 240 ip=1,nsetp
    1348            0 :          l=INDEX(ip)
    1349            0 :          x(l)=(one-alpha)*x(l) + alpha*z(ip)
    1350            0 :   240 CONTINUE
    1351              : 
    1352              : !C .....EXIT LOOP B
    1353              : 
    1354            0 :       IF(jj.EQ.0)                     GOTO 110
    1355              : 
    1356              : !C STEP ELEVEN (DELETE COLUMN)
    1357              : 
    1358            0 :       i=INDEX(jj)
    1359            0 :   250 x(i)=ZERO
    1360            0 :       jj=jj+1
    1361            0 :       DO 260 j=jj,nsetp
    1362            0 :          ii=INDEX(j)
    1363            0 :          INDEX(j-1)=ii
    1364            0 :          CALL dsrotg(a(j-1,ii),a(j,ii),c,s)
    1365            0 :          t=a(j-1,ii)
    1366            0 :          CALL dsrot(n,a(j-1,1),mda,a(j,1),mda,c,s)
    1367            0 :          a(j-1,ii)=t
    1368            0 :          a(j,ii)=ZERO
    1369            0 :          CALL dsrot(1,b(j-1),1,b(j),1,c,s)
    1370            0 :   260 CONTINUE
    1371            0 :       npp1=nsetp
    1372            0 :       nsetp=nsetp-1
    1373            0 :       iz1=iz1-1
    1374            0 :       INDEX(iz1)=i
    1375            0 :       IF(nsetp.LE.0)                  GOTO 210
    1376            0 :       DO 270 jj=1,nsetp
    1377            0 :          i=INDEX(jj)
    1378            0 :          IF(x(i).LE.ZERO)             GOTO 250
    1379            0 :   270 CONTINUE
    1380            0 :       CALL dcopy_(m,b,1,z,1)
    1381            0 :                                       GOTO 180
    1382              : !C STEP TWELVE (SOLUTION)
    1383              : 
    1384            0 :   280 k=MIN(npp1,m)
    1385            0 :       rnorm=dnrm2_(m-nsetp,b(k),1)
    1386            0 :       IF(npp1.GT.m) THEN
    1387            0 :          w(1)=ZERO
    1388            0 :          CALL dcopy_(n,w(1),0,w,1)
    1389              :       ENDIF
    1390              : 
    1391              : !C END OF SUBROUTINE NNLS
    1392              : 
    1393              :   290 CONTINUE
    1394              : 
    1395            0 :       END SUBROUTINE nnls
    1396              : 
    1397            0 :       SUBROUTINE hfti(a,mda,m,n,b,mdb,nb,tau,krank,rnorm,h,g,ip)
    1398              : 
    1399              : !C     RANK-DEFICIENT LEAST SQUARES ALGORITHM AS DESCRIBED IN:
    1400              : !C     C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12
    1401              : !C     TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974
    1402              : 
    1403              : !C     A(*,*),MDA,M,N   THE ARRAY A INITIALLY CONTAINS THE M x N MATRIX A
    1404              : !C                      OF THE LEAST SQUARES PROBLEM AX = B.
    1405              : !C                      THE FIRST DIMENSIONING PARAMETER MDA MUST SATISFY
    1406              : !C                      MDA >= M. EITHER M >= N OR M < N IS PERMITTED.
    1407              : !C                      THERE IS NO RESTRICTION ON THE RANK OF A.
    1408              : !C                      THE MATRIX A WILL BE MODIFIED BY THE SUBROUTINE.
    1409              : !C     B(*,*),MDB,NB    IF NB = 0 THE SUBROUTINE WILL MAKE NO REFERENCE
    1410              : !C                      TO THE ARRAY B. IF NB > 0 THE ARRAY B() MUST
    1411              : !C                      INITIALLY CONTAIN THE M x NB MATRIX B  OF THE
    1412              : !C                      THE LEAST SQUARES PROBLEM AX = B AND ON RETURN
    1413              : !C                      THE ARRAY B() WILL CONTAIN THE N x NB SOLUTION X.
    1414              : !C                      IF NB>1 THE ARRAY B() MUST BE DOUBLE SUBSCRIPTED
    1415              : !C                      WITH FIRST DIMENSIONING PARAMETER MDB>=MAX(M,N),
    1416              : !C                      IF NB=1 THE ARRAY B() MAY BE EITHER SINGLE OR
    1417              : !C                      DOUBLE SUBSCRIPTED.
    1418              : !C     TAU              ABSOLUTE TOLERANCE PARAMETER FOR PSEUDORANK
    1419              : !C                      DETERMINATION, PROVIDED BY THE USER.
    1420              : !C     KRANK            PSEUDORANK OF A, SET BY THE SUBROUTINE.
    1421              : !C     RNORM            ON EXIT, RNORM(J) WILL CONTAIN THE EUCLIDIAN
    1422              : !C                      NORM OF THE RESIDUAL VECTOR FOR THE PROBLEM
    1423              : !C                      DEFINED BY THE J-TH COLUMN VECTOR OF THE ARRAY B.
    1424              : !C     H(), G()         ARRAYS OF WORKING SPACE OF LENGTH >= N.
    1425              : !C     IP()             INTEGER ARRAY OF WORKING SPACE OF LENGTH >= N
    1426              : !C                      RECORDING PERMUTATION INDICES OF COLUMN VECTORS
    1427              : 
    1428              :       INTEGER          i,j,jb,k,kp1,krank,l,ldiag,lmax,m,&
    1429              :                        mda,mdb,n,nb,ip(n)
    1430              :       DOUBLE PRECISION a(mda,n),b(mdb,nb),h(n),g(n),rnorm(nb),factor,&
    1431              :                        tau,ZERO,hmax,diff,tmp,u,v
    1432              :       diff(u,v)=       u-v
    1433              :       DATA             ZERO/0.0d0/, factor/1.0d-3/
    1434              : 
    1435            0 :       k=0
    1436            0 :       ldiag=MIN(m,n)
    1437            0 :       IF(ldiag.LE.0)                  GOTO 270
    1438              : 
    1439              : !C   COMPUTE LMAX
    1440              : 
    1441            0 :       DO 80 j=1,ldiag
    1442            0 :           IF(j.EQ.1)                  GOTO 20
    1443              :           lmax=j
    1444            0 :           DO 10 l=j,n
    1445            0 :               h(l)=h(l)-a(j-1,l)**2
    1446            0 :               IF(h(l).GT.h(lmax)) lmax=l
    1447            0 :    10     CONTINUE
    1448            0 :           IF(diff(hmax+factor*h(lmax),hmax).GT.ZERO)&
    1449              :                                       GOTO 50
    1450            0 :    20     lmax=j
    1451            0 :           DO 40 l=j,n
    1452            0 :               h(l)=ZERO
    1453            0 :               DO 30 i=j,m
    1454            0 :                   h(l)=h(l)+a(i,l)**2
    1455            0 :    30         CONTINUE
    1456            0 :               IF(h(l).GT.h(lmax)) lmax=l
    1457            0 :    40     CONTINUE
    1458            0 :           hmax=h(lmax)
    1459              : 
    1460              : !C   COLUMN INTERCHANGES IF NEEDED
    1461              : 
    1462            0 :    50     ip(j)=lmax
    1463            0 :           IF(ip(j).EQ.j)              GOTO 70
    1464            0 :           DO 60 i=1,m
    1465            0 :               tmp=a(i,j)
    1466            0 :               a(i,j)=a(i,lmax)
    1467            0 :               a(i,lmax)=tmp
    1468            0 :    60     CONTINUE
    1469            0 :           h(lmax)=h(j)
    1470              : 
    1471              : !C   J-TH TRANSFORMATION AND APPLICATION TO A AND B
    1472              : 
    1473            0 :    70     i=MIN(j+1,n)
    1474            0 :           CALL h12(1,j,j+1,m,a(1,j),1,h(j),a(1,i),1,mda,n-j)
    1475            0 :           CALL h12(2,j,j+1,m,a(1,j),1,h(j),b,1,mdb,nb)
    1476            0 :    80 CONTINUE
    1477              : 
    1478              : !C   DETERMINE PSEUDORANK
    1479              : 
    1480            0 :       DO 90 j=1,ldiag
    1481            0 :           IF(ABS(a(j,j)).LE.tau)      GOTO 100
    1482            0 :    90 CONTINUE
    1483              :       k=ldiag
    1484            0 :       GOTO 110
    1485            0 :   100 k=j-1
    1486            0 :   110 kp1=k+1
    1487              : 
    1488              : !C   NORM OF RESIDUALS
    1489              : 
    1490            0 :       DO 130 jb=1,nb
    1491            0 :           rnorm(jb)=dnrm2_(m-k,b(kp1,jb),1)
    1492            0 :   130 CONTINUE
    1493            0 :       IF(k.GT.0)                      GOTO 160
    1494            0 :       DO 150 jb=1,nb
    1495            0 :           DO 149 i=1,n
    1496            0 :               b(i,jb)=ZERO
    1497            0 :   149     CONTINUE
    1498            0 :   150 CONTINUE
    1499            0 :       GOTO 270
    1500            0 :   160 IF(k.EQ.n)                      GOTO 180
    1501              : 
    1502              : !C   HOUSEHOLDER DECOMPOSITION OF FIRST K ROWS
    1503              : 
    1504            0 :       DO 170 i=k,1,-1
    1505            0 :           CALL h12(1,i,kp1,n,a(i,1),mda,g(i),a,mda,1,i-1)
    1506            0 :   170 CONTINUE
    1507            0 :   180 DO 250 jb=1,nb
    1508              : 
    1509              : !C   SOLVE K*K TRIANGULAR SYSTEM
    1510              : 
    1511            0 :           DO 210 i=k,1,-1
    1512            0 :               j=MIN(i+1,n)
    1513            0 :               b(i,jb)=(b(i,jb)-ddot_sl(k-i,a(i,j),mda,b(j,jb),1))/a(i,i)
    1514            0 :   210     CONTINUE
    1515              : 
    1516              : !C   COMPLETE SOLUTION VECTOR
    1517              : 
    1518            0 :           IF(k.EQ.n)                  GOTO 240
    1519            0 :           DO 220 j=kp1,n
    1520            0 :               b(j,jb)=ZERO
    1521            0 :   220     CONTINUE
    1522            0 :           DO 230 i=1,k
    1523            0 :               CALL h12(2,i,kp1,n,a(i,1),mda,g(i),b(1,jb),1,mdb,1)
    1524            0 :   230     CONTINUE
    1525              : 
    1526              : !C   REORDER SOLUTION ACCORDING TO PREVIOUS COLUMN INTERCHANGES
    1527              : 
    1528            0 :   240     DO 249 j=ldiag,1,-1
    1529            0 :               IF(ip(j).EQ.j)          GOTO 249
    1530            0 :               l=ip(j)
    1531            0 :               tmp=b(l,jb)
    1532            0 :               b(l,jb)=b(j,jb)
    1533            0 :               b(j,jb)=tmp
    1534            0 :   249     CONTINUE
    1535            0 :   250 CONTINUE
    1536            0 :   270 krank=k
    1537            0 :       END SUBROUTINE hfti
    1538              : 
    1539            0 :       SUBROUTINE h12 (mode,lpivot,l1,m,u,iue,up,c,ice,icv,ncv)
    1540              : 
    1541              : !C     C.L.LAWSON AND R.J.HANSON, JET PROPULSION LABORATORY, 1973 JUN 12
    1542              : !C     TO APPEAR IN 'SOLVING LEAST SQUARES PROBLEMS', PRENTICE-HALL, 1974
    1543              : 
    1544              : !C     CONSTRUCTION AND/OR APPLICATION OF A SINGLE
    1545              : !C     HOUSEHOLDER TRANSFORMATION  Q = I + U*(U**T)/B
    1546              : 
    1547              : !C     MODE    = 1 OR 2   TO SELECT ALGORITHM  H1  OR  H2 .
    1548              : !C     LPIVOT IS THE INDEX OF THE PIVOT ELEMENT.
    1549              : !C     L1,M   IF L1 <= M   THE TRANSFORMATION WILL BE CONSTRUCTED TO
    1550              : !C            ZERO ELEMENTS INDEXED FROM L1 THROUGH M.
    1551              : !C            IF L1 > M THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION.
    1552              : !C     U(),IUE,UP
    1553              : !C            ON ENTRY TO H1 U() STORES THE PIVOT VECTOR.
    1554              : !C            IUE IS THE STORAGE INCREMENT BETWEEN ELEMENTS.
    1555              : !C            ON EXIT FROM H1 U() AND UP STORE QUANTITIES DEFINING
    1556              : !C            THE VECTOR U OF THE HOUSEHOLDER TRANSFORMATION.
    1557              : !C            ON ENTRY TO H2 U() AND UP
    1558              : !C            SHOULD STORE QUANTITIES PREVIOUSLY COMPUTED BY H1.
    1559              : !C            THESE WILL NOT BE MODIFIED BY H2.
    1560              : !C     C()    ON ENTRY TO H1 OR H2 C() STORES A MATRIX WHICH WILL BE
    1561              : !C            REGARDED AS A SET OF VECTORS TO WHICH THE HOUSEHOLDER
    1562              : !C            TRANSFORMATION IS TO BE APPLIED.
    1563              : !C            ON EXIT C() STORES THE SET OF TRANSFORMED VECTORS.
    1564              : !C     ICE    STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C().
    1565              : !C     ICV    STORAGE INCREMENT BETWEEN VECTORS IN C().
    1566              : !C     NCV    NUMBER OF VECTORS IN C() TO BE TRANSFORMED.
    1567              : !C            IF NCV <= 0 NO OPERATIONS WILL BE DONE ON C().
    1568              : 
    1569              :       INTEGER          incr, ice, icv, iue, lpivot, l1, mode, ncv
    1570              :       INTEGER          i, i2, i3, i4, j, m
    1571              :       DOUBLE PRECISION u,up,c,cl,clinv,b,sm,one,ZERO
    1572              :       DIMENSION        u(iue,*), c(*)
    1573              :       DATA             one/1.0d+00/, ZERO/0.0d+00/
    1574              : 
    1575            0 :       IF (0.GE.lpivot.OR.lpivot.GE.l1.OR.l1.GT.m) GOTO 80
    1576            0 :       cl=ABS(u(1,lpivot))
    1577            0 :       IF (mode.EQ.2)                              GOTO 30
    1578              : 
    1579              : !C     ****** CONSTRUCT THE TRANSFORMATION ******
    1580              : 
    1581            0 :           DO 10 j=l1,m
    1582            0 :              sm=ABS(u(1,j))
    1583            0 :           cl=MAX(sm,cl)
    1584            0 :    10     CONTINUE
    1585            0 :       IF (cl.LE.ZERO)                             GOTO 80
    1586            0 :       clinv=one/cl
    1587            0 :       sm=(u(1,lpivot)*clinv)**2
    1588            0 :           DO 20 j=l1,m
    1589            0 :           sm=sm+(u(1,j)*clinv)**2
    1590            0 :    20     CONTINUE
    1591            0 :       cl=cl*SQRT(sm)
    1592            0 :       IF (u(1,lpivot).GT.ZERO) cl=-cl
    1593            0 :       up=u(1,lpivot)-cl
    1594            0 :       u(1,lpivot)=cl
    1595            0 :                                                   GOTO 40
    1596              : !C     ****** APPLY THE TRANSFORMATION  I+U*(U**T)/B  TO C ******
    1597              : 
    1598            0 :    30 IF (cl.LE.ZERO)                             GOTO 80
    1599            0 :    40 IF (ncv.LE.0)                               GOTO 80
    1600            0 :       b=up*u(1,lpivot)
    1601            0 :       IF (b.GE.ZERO)                              GOTO 80
    1602            0 :       b=one/b
    1603            0 :       i2=1-icv+ice*(lpivot-1)
    1604            0 :       incr=ice*(l1-lpivot)
    1605            0 :           DO 70 j=1,ncv
    1606            0 :           i2=i2+icv
    1607            0 :           i3=i2+incr
    1608            0 :           i4=i3
    1609            0 :           sm=c(i2)*up
    1610            0 :               DO 50 i=l1,m
    1611            0 :               sm=sm+c(i3)*u(1,i)
    1612            0 :               i3=i3+ice
    1613            0 :    50         CONTINUE
    1614            0 :           IF (sm.EQ.ZERO)                         GOTO 70
    1615            0 :           sm=sm*b
    1616            0 :           c(i2)=c(i2)+sm*up
    1617            0 :               DO 60 i=l1,m
    1618            0 :               c(i4)=c(i4)+sm*u(1,i)
    1619            0 :               i4=i4+ice
    1620            0 :    60         CONTINUE
    1621            0 :    70     CONTINUE
    1622              :    80     CONTINUE
    1623              : 
    1624            0 :       END SUBROUTINE h12
    1625              : 
    1626            0 :       SUBROUTINE ldl (n,a,z,sigma,w)
    1627              : !C   LDL     LDL' - RANK-ONE - UPDATE
    1628              : 
    1629              : !C   PURPOSE:
    1630              : !C           UPDATES THE LDL' FACTORS OF MATRIX A BY RANK-ONE MATRIX
    1631              : !C           SIGMA*Z*Z'
    1632              : 
    1633              : !C   INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION)
    1634              : !C     N     : ORDER OF THE COEFFICIENT MATRIX A
    1635              : !C   * A     : POSITIVE DEFINITE MATRIX OF DIMENSION N;
    1636              : !C             ONLY THE LOWER TRIANGLE IS USED AND IS STORED COLUMN BY
    1637              : !C             COLUMN AS ONE DIMENSIONAL ARRAY OF DIMENSION N*(N+1)/2.
    1638              : !C   * Z     : VECTOR OF DIMENSION N OF UPDATING ELEMENTS
    1639              : !C     SIGMA : SCALAR FACTOR BY WHICH THE MODIFYING DYADE Z*Z' IS
    1640              : !C             MULTIPLIED
    1641              : 
    1642              : !C   OUTPUT ARGUMENTS:
    1643              : !C     A     : UPDATED LDL' FACTORS
    1644              : 
    1645              : !C   WORKING ARRAY:
    1646              : !C     W     : VECTOR OP DIMENSION N (USED ONLY IF SIGMA .LT. ZERO)
    1647              : 
    1648              : !C   METHOD:
    1649              : !C     THAT OF FLETCHER AND POWELL AS DESCRIBED IN :
    1650              : !C     FLETCHER,R.,(1974) ON THE MODIFICATION OF LDL' FACTORIZATION.
    1651              : !C     POWELL,M.J.D.      MATH.COMPUTATION 28, 1067-1078.
    1652              : 
    1653              : !C   IMPLEMENTED BY:
    1654              : !C     KRAFT,D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME
    1655              : !C               D-8031  OBERPFAFFENHOFEN
    1656              : 
    1657              : !C   STATUS: 15. JANUARY 1980
    1658              : 
    1659              : !C   SUBROUTINES REQUIRED: NONE
    1660              : 
    1661              :       INTEGER          i, ij, j, n
    1662              :       DOUBLE PRECISION a(*), t, v, w(*), z(*), u, tp, one, beta, four,&
    1663              :                        ZERO, alpha, delta, gamma, sigma, epmach
    1664              :       DATA ZERO, one, four, epmach /0.0d0, 1.0d0, 4.0d0, 2.22d-16/
    1665              : 
    1666            0 :       IF(sigma.EQ.ZERO)               GOTO 280
    1667            0 :       ij=1
    1668            0 :       t=one/sigma
    1669            0 :       IF(sigma.GT.ZERO)               GOTO 220
    1670              : !C PREPARE NEGATIVE UPDATE
    1671            0 :       DO 150 i=1,n
    1672            0 :           w(i)=z(i)
    1673            0 :   150 CONTINUE
    1674            0 :       DO 170 i=1,n
    1675            0 :           v=w(i)
    1676            0 :           t=t+v*v/a(ij)
    1677            0 :           DO 160 j=i+1,n
    1678            0 :               ij=ij+1
    1679            0 :               w(j)=w(j)-v*a(ij)
    1680            0 :   160     CONTINUE
    1681            0 :           ij=ij+1
    1682            0 :   170 CONTINUE
    1683            0 :       IF(t.GE.ZERO) t=epmach/sigma
    1684            0 :       DO 210 i=1,n
    1685            0 :           j=n+1-i
    1686            0 :           ij=ij-i
    1687            0 :           u=w(j)
    1688            0 :           w(j)=t
    1689            0 :           t=t-u*u/a(ij)
    1690            0 :   210 CONTINUE
    1691              :   220 CONTINUE
    1692              : !C HERE UPDATING BEGINS
    1693            0 :       DO 270 i=1,n
    1694            0 :           v=z(i)
    1695            0 :           delta=v/a(ij)
    1696            0 :           IF(sigma.LT.ZERO) tp=w(i)
    1697            0 :           IF(sigma.GT.ZERO) tp=t+delta*v
    1698            0 :           alpha=tp/t
    1699            0 :           a(ij)=alpha*a(ij)
    1700            0 :           IF(i.EQ.n)                  GOTO 280
    1701            0 :           beta=delta/tp
    1702            0 :           IF(alpha.GT.four)           GOTO 240
    1703            0 :           DO 230 j=i+1,n
    1704            0 :               ij=ij+1
    1705            0 :               z(j)=z(j)-v*a(ij)
    1706            0 :               a(ij)=a(ij)+beta*z(j)
    1707            0 :   230     CONTINUE
    1708            0 :                                       GOTO 260
    1709            0 :   240     gamma=t/tp
    1710            0 :           DO 250 j=i+1,n
    1711            0 :               ij=ij+1
    1712            0 :               u=a(ij)
    1713            0 :               a(ij)=gamma*u+beta*z(j)
    1714            0 :               z(j)=z(j)-v*u
    1715            0 :   250     CONTINUE
    1716            0 :   260     ij=ij+1
    1717            0 :           t=tp
    1718            0 :   270 CONTINUE
    1719            0 :   280 RETURN
    1720              : !C END OF LDL
    1721              :       END SUBROUTINE ldl
    1722              : 
    1723            0 :       DOUBLE PRECISION FUNCTION linmin (mode, ax, bx, f, tol)
    1724              : !C   LINMIN  LINESEARCH WITHOUT DERIVATIVES
    1725              : 
    1726              : !C   PURPOSE:
    1727              : 
    1728              : !C  TO FIND THE ARGUMENT LINMIN WHERE THE FUNCTION F TAKES IT'S MINIMUM
    1729              : !C  ON THE INTERVAL AX, BX.
    1730              : !C  COMBINATION OF GOLDEN SECTION AND SUCCESSIVE QUADRATIC INTERPOLATION.
    1731              : 
    1732              : !C   INPUT ARGUMENTS: (* MEANS PARAMETERS ARE CHANGED DURING EXECUTION)
    1733              : 
    1734              : !C *MODE   SEE OUTPUT ARGUMENTS
    1735              : !C  AX     LEFT ENDPOINT OF INITIAL INTERVAL
    1736              : !C  BX     RIGHT ENDPOINT OF INITIAL INTERVAL
    1737              : !C  F      FUNCTION VALUE AT LINMIN WHICH IS TO BE BROUGHT IN BY
    1738              : !C         REVERSE COMMUNICATION CONTROLLED BY MODE
    1739              : !C  TOL    DESIRED LENGTH OF INTERVAL OF UNCERTAINTY OF FINAL RESULT
    1740              : 
    1741              : !C   OUTPUT ARGUMENTS:
    1742              : 
    1743              : !C  LINMIN ABSCISSA APPROXIMATING THE POINT WHERE F ATTAINS A MINIMUM
    1744              : !C  MODE   CONTROLS REVERSE COMMUNICATION
    1745              : !C         MUST BE SET TO 0 INITIALLY, RETURNS WITH INTERMEDIATE
    1746              : !C         VALUES 1 AND 2 WHICH MUST NOT BE CHANGED BY THE USER,
    1747              : !C         ENDS WITH CONVERGENCE WITH VALUE 3.
    1748              : 
    1749              : !C   WORKING ARRAY:
    1750              : 
    1751              : !C  NONE
    1752              : 
    1753              : !C   METHOD:
    1754              : 
    1755              : !C  THIS FUNCTION SUBPROGRAM IS A SLIGHTLY MODIFIED VERSION OF THE
    1756              : !C  ALGOL 60 PROCEDURE LOCALMIN GIVEN IN
    1757              : !C  R.P. BRENT: ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES,
    1758              : !C              PRENTICE-HALL (1973).
    1759              : 
    1760              : !C   IMPLEMENTED BY:
    1761              : 
    1762              : !C     KRAFT, D., DFVLR - INSTITUT FUER DYNAMIK DER FLUGSYSTEME
    1763              : !C                D-8031  OBERPFAFFENHOFEN
    1764              : 
    1765              : !C   STATUS: 31. AUGUST  1984
    1766              : 
    1767              : !C   SUBROUTINES REQUIRED: NONE
    1768              : 
    1769              :       INTEGER          mode
    1770              :       DOUBLE PRECISION f, tol, a, b, c, d, e, p, q, r, u, v, w, x, m,&
    1771              :      &                 fu, fv, fw, fx, eps, tol1, tol2, ZERO, ax, bx
    1772              :       DATA             c /0.381966011d0/, eps /1.5d-8/, ZERO /0.0d0/
    1773              : 
    1774              : !C  EPS = SQUARE - ROOT OF MACHINE PRECISION
    1775              : !C  C = GOLDEN SECTION RATIO = (3-SQRT(5))/2
    1776              : 
    1777            0 :       GOTO (10, 55), mode
    1778              : 
    1779              : !C  INITIALIZATION
    1780              : 
    1781            0 :       a = ax
    1782            0 :       b = bx
    1783            0 :       e = ZERO
    1784            0 :       v = a + c*(b - a)
    1785            0 :       w = v
    1786            0 :       x = w
    1787            0 :       linmin = x
    1788            0 :       mode = 1
    1789            0 :       GOTO 100
    1790              : 
    1791              : !C  MAIN LOOP STARTS HERE
    1792              : 
    1793            0 :    10 fx = f
    1794            0 :       fv = fx
    1795            0 :       fw = fv
    1796            0 :    20 m = 0.5d0*(a + b)
    1797            0 :       tol1 = eps*ABS(x) + tol
    1798            0 :       tol2 = tol1 + tol1
    1799              : 
    1800              : !C  TEST CONVERGENCE
    1801              : 
    1802            0 :       IF (ABS(x - m) .LE. tol2 - 0.5d0*(b - a)) GOTO 90
    1803            0 :       r = ZERO
    1804            0 :       q = r
    1805            0 :       p = q
    1806            0 :       IF (ABS(e) .LE. tol1) GOTO 30
    1807              : 
    1808              : !C  FIT PARABOLA
    1809              : 
    1810            0 :       r = (x - w)*(fx - fv)
    1811            0 :       q = (x - v)*(fx - fw)
    1812            0 :       p = (x - v)*q - (x - w)*r
    1813            0 :       q = q - r
    1814            0 :       q = q + q
    1815            0 :       IF (q .GT. ZERO) p = -p
    1816            0 :       IF (q .LT. ZERO) q = -q
    1817              :       r = e
    1818            0 :       e = d
    1819              : 
    1820              : !C  IS PARABOLA ACCEPTABLE
    1821              : 
    1822              :    30 IF (ABS(p) .GE. 0.5d0*ABS(q*r) .OR.&
    1823            0 :      &    p .LE. q*(a - x) .OR. p .GE. q*(b-x)) GOTO 40
    1824              : 
    1825              : !C  PARABOLIC INTERPOLATION STEP
    1826              : 
    1827            0 :       d = p/q
    1828              : 
    1829              : !C  F MUST NOT BE EVALUATED TOO CLOSE TO A OR B
    1830              : 
    1831            0 :       IF (u - a .LT. tol2) d = SIGN(tol1, m - x)
    1832            0 :       IF (b - u .LT. tol2) d = SIGN(tol1, m - x)
    1833            0 :       GOTO 50
    1834              : 
    1835              : !C  GOLDEN SECTION STEP
    1836              : 
    1837            0 :    40 IF (x .GE. m) e = a - x
    1838            0 :       IF (x .LT. m) e = b - x
    1839            0 :       d = c*e
    1840              : 
    1841              : !C  F MUST NOT BE EVALUATED TOO CLOSE TO X
    1842              : 
    1843            0 :    50 IF (ABS(d) .LT. tol1) d = SIGN(tol1, d)
    1844            0 :       u = x + d
    1845            0 :       linmin = u
    1846            0 :       mode = 2
    1847            0 :       GOTO 100
    1848            0 :    55 fu = f
    1849              : 
    1850              : !C  UPDATE A, B, V, W, AND X
    1851              : 
    1852            0 :       IF (fu .GT. fx) GOTO 60
    1853              :       IF (u .GE. x) a = x
    1854              :       IF (u .LT. x) b = x
    1855              :       v = w
    1856              :       fv = fw
    1857              :       w = x
    1858              :       fw = fx
    1859              :       x = u
    1860              :       fx = fu
    1861            0 :       GOTO 85
    1862              :    60 IF (u .LT. x) a = u
    1863              :       IF (u .GE. x) b = u
    1864            0 :       IF (fu .LE. fw .OR. w .EQ. x) GOTO 70
    1865            0 :       IF (fu .LE. fv .OR. v .EQ. x .OR. v .EQ. w) GOTO 80
    1866            0 :       GOTO 85
    1867              :    70 v = w
    1868              :       fv = fw
    1869              :       w = u
    1870              :       fw = fu
    1871            0 :       GOTO 85
    1872            0 :    80 v = u
    1873            0 :       fv = fu
    1874            0 :    85 GOTO 20
    1875              : 
    1876              : !C  END OF MAIN LOOP
    1877              : 
    1878            0 :    90 linmin = x
    1879            0 :       mode = 3
    1880              :   100 RETURN
    1881              : 
    1882              : !C  END OF LINMIN
    1883              : 
    1884              :       END FUNCTION linmin
    1885              : 
    1886              : !C## Following a selection from BLAS Level 1
    1887              : 
    1888            0 :       SUBROUTINE daxpy_sl(n,da,dx,incx,dy,incy)
    1889              : 
    1890              : !C     CONSTANT TIMES A VECTOR PLUS A VECTOR.
    1891              : !C     USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE.
    1892              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    1893              : 
    1894              :       DOUBLE PRECISION dx(*),dy(*),da
    1895              :       INTEGER i,incx,incy,ix,iy,m,mp1,n
    1896              : 
    1897            0 :       IF(n.LE.0)RETURN
    1898            0 :       IF(da.EQ.0.0d0)RETURN
    1899            0 :       IF(incx.EQ.1.AND.incy.EQ.1)GO TO 20
    1900              : 
    1901              : !C        CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS
    1902              : !C        NOT EQUAL TO 1
    1903              : 
    1904            0 :       ix = 1
    1905            0 :       iy = 1
    1906            0 :       IF(incx.LT.0)ix = (-n+1)*incx + 1
    1907            0 :       IF(incy.LT.0)iy = (-n+1)*incy + 1
    1908            0 :       DO 10 i = 1,n
    1909            0 :         dy(iy) = dy(iy) + da*dx(ix)
    1910            0 :         ix = ix + incx
    1911            0 :         iy = iy + incy
    1912            0 :    10 CONTINUE
    1913            0 :       RETURN
    1914              : 
    1915              : !C        CODE FOR BOTH INCREMENTS EQUAL TO 1
    1916              : 
    1917              : !C        CLEAN-UP LOOP
    1918              : 
    1919            0 :    20 m = MOD(n,4)
    1920            0 :       IF( m .EQ. 0 ) GO TO 40
    1921            0 :       DO 30 i = 1,m
    1922            0 :         dy(i) = dy(i) + da*dx(i)
    1923            0 :    30 CONTINUE
    1924            0 :       IF( n .LT. 4 ) RETURN
    1925            0 :    40 mp1 = m + 1
    1926            0 :       DO 50 i = mp1,n,4
    1927            0 :         dy(i) = dy(i) + da*dx(i)
    1928            0 :         dy(i + 1) = dy(i + 1) + da*dx(i + 1)
    1929            0 :         dy(i + 2) = dy(i + 2) + da*dx(i + 2)
    1930            0 :         dy(i + 3) = dy(i + 3) + da*dx(i + 3)
    1931            0 :    50 CONTINUE
    1932              :       RETURN
    1933              :       END SUBROUTINE daxpy_sl
    1934              : 
    1935            0 :       SUBROUTINE  dcopy_(n,dx,incx,dy,incy)
    1936              : 
    1937              : !C     COPIES A VECTOR, X, TO A VECTOR, Y.
    1938              : !C     USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE.
    1939              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    1940              : 
    1941              :       DOUBLE PRECISION dx(*),dy(*)
    1942              :       INTEGER i,incx,incy,ix,iy,m,mp1,n
    1943              : 
    1944            0 :       IF(n.LE.0)RETURN
    1945            0 :       IF(incx.EQ.1.AND.incy.EQ.1)GO TO 20
    1946              : 
    1947              : !C        CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS
    1948              : !C        NOT EQUAL TO 1
    1949              : 
    1950            0 :       ix = 1
    1951            0 :       iy = 1
    1952            0 :       IF(incx.LT.0)ix = (-n+1)*incx + 1
    1953            0 :       IF(incy.LT.0)iy = (-n+1)*incy + 1
    1954            0 :       DO 10 i = 1,n
    1955            0 :         dy(iy) = dx(ix)
    1956            0 :         ix = ix + incx
    1957            0 :         iy = iy + incy
    1958            0 :    10 CONTINUE
    1959            0 :       RETURN
    1960              : 
    1961              : !C        CODE FOR BOTH INCREMENTS EQUAL TO 1
    1962              : 
    1963              : !C        CLEAN-UP LOOP
    1964              : 
    1965            0 :    20 m = MOD(n,7)
    1966            0 :       IF( m .EQ. 0 ) GO TO 40
    1967            0 :       DO 30 i = 1,m
    1968            0 :         dy(i) = dx(i)
    1969            0 :    30 CONTINUE
    1970            0 :       IF( n .LT. 7 ) RETURN
    1971            0 :    40 mp1 = m + 1
    1972            0 :       DO 50 i = mp1,n,7
    1973            0 :         dy(i) = dx(i)
    1974            0 :         dy(i + 1) = dx(i + 1)
    1975            0 :         dy(i + 2) = dx(i + 2)
    1976            0 :         dy(i + 3) = dx(i + 3)
    1977            0 :         dy(i + 4) = dx(i + 4)
    1978            0 :         dy(i + 5) = dx(i + 5)
    1979            0 :         dy(i + 6) = dx(i + 6)
    1980            0 :    50 CONTINUE
    1981              :       RETURN
    1982              :       END SUBROUTINE dcopy_
    1983              : 
    1984            0 :       DOUBLE PRECISION FUNCTION ddot_sl(n,dx,incx,dy,incy)
    1985              : 
    1986              : !C     FORMS THE DOT PRODUCT OF TWO VECTORS.
    1987              : !C     USES UNROLLED LOOPS FOR INCREMENTS EQUAL TO ONE.
    1988              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    1989              : 
    1990              :       DOUBLE PRECISION dx(*),dy(*),dtemp
    1991              :       INTEGER i,incx,incy,ix,iy,m,mp1,n
    1992              : 
    1993            0 :       ddot_sl = 0.0d0
    1994            0 :       dtemp = 0.0d0
    1995            0 :       IF(n.LE.0)RETURN
    1996            0 :       IF(incx.EQ.1.AND.incy.EQ.1)GO TO 20
    1997              : 
    1998              : !C        CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS
    1999              : !C          NOT EQUAL TO 1
    2000              : 
    2001            0 :       ix = 1
    2002            0 :       iy = 1
    2003            0 :       IF(incx.LT.0)ix = (-n+1)*incx + 1
    2004            0 :       IF(incy.LT.0)iy = (-n+1)*incy + 1
    2005            0 :       DO 10 i = 1,n
    2006            0 :         dtemp = dtemp + dx(ix)*dy(iy)
    2007            0 :         ix = ix + incx
    2008            0 :         iy = iy + incy
    2009            0 :    10 CONTINUE
    2010            0 :       ddot_sl = dtemp
    2011            0 :       RETURN
    2012              : 
    2013              : !C        CODE FOR BOTH INCREMENTS EQUAL TO 1
    2014              : 
    2015              : !C        CLEAN-UP LOOP
    2016              : 
    2017            0 :    20 m = MOD(n,5)
    2018            0 :       IF( m .EQ. 0 ) GO TO 40
    2019            0 :       DO 30 i = 1,m
    2020            0 :         dtemp = dtemp + dx(i)*dy(i)
    2021            0 :    30 CONTINUE
    2022            0 :       IF( n .LT. 5 ) GO TO 60
    2023            0 :    40 mp1 = m + 1
    2024            0 :       DO 50 i = mp1,n,5
    2025              :         dtemp = dtemp + dx(i)*dy(i) + dx(i + 1)*dy(i + 1) + &
    2026            0 :          dx(i + 2)*dy(i + 2) + dx(i + 3)*dy(i + 3) + dx(i + 4)*dy(i + 4)
    2027            0 :    50 CONTINUE
    2028              :    60 ddot_sl = dtemp
    2029              :       RETURN
    2030              :       END FUNCTION ddot_sl
    2031              : 
    2032              :       DOUBLE PRECISION FUNCTION dnrm1(n,x,i,j)
    2033              :       INTEGER n, i, j, k
    2034              :       DOUBLE PRECISION snormx, sum, x(n), ZERO, one, scale, temp
    2035              :       DATA ZERO/0.0d0/, one/1.0d0/
    2036              : 
    2037              : !C      DNRM1 - COMPUTES THE I-NORM OF A VECTOR
    2038              : !C              BETWEEN THE ITH AND THE JTH ELEMENTS
    2039              : 
    2040              : !C      INPUT -
    2041              : !C      N       LENGTH OF VECTOR
    2042              : !C      X       VECTOR OF LENGTH N
    2043              : !C      I       INITIAL ELEMENT OF VECTOR TO BE USED
    2044              : !C      J       FINAL ELEMENT TO USE
    2045              : 
    2046              : !C      OUTPUT -
    2047              : !C      DNRM1   NORM
    2048              : 
    2049              :       snormx=ZERO
    2050              :       DO 10 k=i,j
    2051              :          snormx=MAX(snormx,ABS(x(k)))
    2052              :  10   CONTINUE
    2053              :       dnrm1 = snormx
    2054              :       IF (snormx.EQ.ZERO) RETURN
    2055              :       scale = snormx
    2056              :       IF (snormx.GE.one) scale=SQRT(snormx)
    2057              :       sum=ZERO
    2058              :       DO 20 k=i,j
    2059              :          temp=ZERO
    2060              :          IF (ABS(x(k))+scale .NE. scale) temp = x(k)/snormx
    2061              :          IF (one+temp.NE.one) sum = sum+temp*temp
    2062              :  20      CONTINUE
    2063              :       sum=SQRT(sum)
    2064              :       dnrm1=snormx*sum
    2065              :       RETURN
    2066              :       END FUNCTION dnrm1
    2067              : 
    2068            0 :       DOUBLE PRECISION FUNCTION dnrm2_ ( n, dx, incx)
    2069              :       INTEGER          n, i, j, nn, next, incx
    2070              :       DOUBLE PRECISION dx(*), cutlo, cuthi, hitest, sum, xmax, ZERO, one
    2071              :       DATA             ZERO, one /0.0d0, 1.0d0/
    2072              : 
    2073              : !C     EUCLIDEAN NORM OF THE N-VECTOR STORED IN DX() WITH STORAGE
    2074              : !C     INCREMENT INCX .
    2075              : !C     IF    N .LE. 0 RETURN WITH RESULT = 0.
    2076              : !C     IF N .GE. 1 THEN INCX MUST BE .GE. 1
    2077              : 
    2078              : !C           C.L.LAWSON, 1978 JAN 08
    2079              : 
    2080              : !C     FOUR PHASE METHOD     USING TWO BUILT-IN CONSTANTS THAT ARE
    2081              : !C     HOPEFULLY APPLICABLE TO ALL MACHINES.
    2082              : !C         CUTLO = MAXIMUM OF  SQRT(U/EPS)   OVER ALL KNOWN MACHINES.
    2083              : !C         CUTHI = MINIMUM OF  SQRT(V)       OVER ALL KNOWN MACHINES.
    2084              : !C     WHERE
    2085              : !C         EPS = SMALLEST NO. SUCH THAT EPS + 1. .GT. 1.
    2086              : !C         U   = SMALLEST POSITIVE NO.   (UNDERFLOW LIMIT)
    2087              : !C         V   = LARGEST  NO.            (OVERFLOW  LIMIT)
    2088              : 
    2089              : !C     BRIEF OUTLINE OF ALGORITHM..
    2090              : 
    2091              : !C     PHASE 1    SCANS ZERO COMPONENTS.
    2092              : !C     MOVE TO PHASE 2 WHEN A COMPONENT IS NONZERO AND .LE. CUTLO
    2093              : !C     MOVE TO PHASE 3 WHEN A COMPONENT IS .GT. CUTLO
    2094              : !C     MOVE TO PHASE 4 WHEN A COMPONENT IS .GE. CUTHI/M
    2095              : !C     WHERE M = N FOR X() REAL AND M = 2*N FOR COMPLEX.
    2096              : 
    2097              : !C     VALUES FOR CUTLO AND CUTHI..
    2098              : !C     FROM THE ENVIRONMENTAL PARAMETERS LISTED IN THE IMSL CONVERTER
    2099              : !C     DOCUMENT THE LIMITING VALUES ARE AS FOLLOWS..
    2100              : !C     CUTLO, S.P.   U/EPS = 2**(-102) FOR  HONEYWELL.  CLOSE SECONDS ARE
    2101              : !C                   UNIVAC AND DEC AT 2**(-103)
    2102              : !C                   THUS CUTLO = 2**(-51) = 4.44089E-16
    2103              : !C     CUTHI, S.P.   V = 2**127 FOR UNIVAC, HONEYWELL, AND DEC.
    2104              : !C                   THUS CUTHI = 2**(63.5) = 1.30438E19
    2105              : !C     CUTLO, D.P.   U/EPS = 2**(-67) FOR HONEYWELL AND DEC.
    2106              : !C                   THUS CUTLO = 2**(-33.5) = 8.23181D-11
    2107              : !C     CUTHI, D.P.   SAME AS S.P.  CUTHI = 1.30438D19
    2108              : !C     DATA CUTLO, CUTHI / 8.232D-11,  1.304D19 /
    2109              : !C     DATA CUTLO, CUTHI / 4.441E-16,  1.304E19 /
    2110              :       DATA cutlo, cuthi / 8.232d-11,  1.304d19 /
    2111              : 
    2112            0 :       IF(n .GT. 0) GO TO 10
    2113            0 :          dnrm2_  = ZERO
    2114            0 :          GO TO 300
    2115              : 
    2116            0 :    10 next = 30
    2117            0 :       sum = ZERO
    2118            0 :       nn = n * incx
    2119              : !C                       BEGIN MAIN LOOP
    2120            0 :       i = 1
    2121            0 :    20 IF( next .EQ. 30) GO TO 30
    2122            0 :       IF( next .EQ. 50) GO TO 50
    2123            0 :       IF( next .EQ. 70) GO TO 70
    2124              :       IF( next .EQ. 110) GO TO 110
    2125            0 :    30 IF( ABS(dx(i)) .GT. cutlo) GO TO 85
    2126              :       next = 50
    2127            0 :       xmax = ZERO
    2128              : 
    2129              : !C                        PHASE 1.  SUM IS ZERO
    2130              : 
    2131            0 :    50 IF( dx(i) .EQ. ZERO) GO TO 200
    2132            0 :       IF( ABS(dx(i)) .GT. cutlo) GO TO 85
    2133              : 
    2134              : !C                        PREPARE FOR PHASE 2.
    2135              : 
    2136              :       next = 70
    2137            0 :       GO TO 105
    2138              : 
    2139              : !C                        PREPARE FOR PHASE 4.
    2140              : 
    2141            0 :   100 i = j
    2142            0 :       next = 110
    2143            0 :       sum = (sum / dx(i)) / dx(i)
    2144            0 :   105 xmax = ABS(dx(i))
    2145            0 :       GO TO 115
    2146              : 
    2147              : !C                   PHASE 2.  SUM IS SMALL.
    2148              : !C                             SCALE TO AVOID DESTRUCTIVE UNDERFLOW.
    2149              : 
    2150            0 :    70 IF( ABS(dx(i)) .GT. cutlo ) GO TO 75
    2151              : 
    2152              : !C                   COMMON CODE FOR PHASES 2 AND 4.
    2153              : !C                   IN PHASE 4 SUM IS LARGE.  SCALE TO AVOID OVERFLOW.
    2154              : 
    2155            0 :   110 IF( ABS(dx(i)) .LE. xmax ) GO TO 115
    2156            0 :          sum = one + sum * (xmax / dx(i))**2
    2157            0 :          xmax = ABS(dx(i))
    2158            0 :          GO TO 200
    2159              : 
    2160            0 :   115 sum = sum + (dx(i)/xmax)**2
    2161            0 :       GO TO 200
    2162              : 
    2163              : !C                  PREPARE FOR PHASE 3.
    2164              : 
    2165            0 :    75 sum = (sum * xmax) * xmax
    2166              : 
    2167              : !C     FOR REAL OR D.P. SET HITEST = CUTHI/N
    2168              : !C     FOR COMPLEX      SET HITEST = CUTHI/(2*N)
    2169              : 
    2170            0 :    85 hitest = cuthi/float( n )
    2171              : 
    2172              : !C                   PHASE 3.  SUM IS MID-RANGE.  NO SCALING.
    2173              : 
    2174            0 :       DO 95 j =i,nn,incx
    2175            0 :       IF(ABS(dx(j)) .GE. hitest) GO TO 100
    2176            0 :          sum = sum + dx(j)**2
    2177            0 :    95 CONTINUE
    2178            0 :       dnrm2_ = SQRT( sum )
    2179            0 :       GO TO 300
    2180              : 
    2181              :   200 CONTINUE
    2182            0 :       i = i + incx
    2183            0 :       IF ( i .LE. nn ) GO TO 20
    2184              : 
    2185              : !C              END OF MAIN LOOP.
    2186              : 
    2187              : !C              COMPUTE SQUARE ROOT AND ADJUST FOR SCALING.
    2188              : 
    2189            0 :       dnrm2_ = xmax * SQRT(sum)
    2190              :   300 CONTINUE
    2191              :       RETURN
    2192              :       END FUNCTION dnrm2_
    2193              : 
    2194            0 :       SUBROUTINE  dsrot (n,dx,incx,dy,incy,c,s)
    2195              : 
    2196              : !C     APPLIES A PLANE ROTATION.
    2197              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    2198              : 
    2199              :       DOUBLE PRECISION dx(*),dy(*),dtemp,c,s
    2200              :       INTEGER i,incx,incy,ix,iy,n
    2201              : 
    2202            0 :       IF(n.LE.0)RETURN
    2203            0 :       IF(incx.EQ.1.AND.incy.EQ.1)GO TO 20
    2204              : 
    2205              : !C       CODE FOR UNEQUAL INCREMENTS OR EQUAL INCREMENTS NOT EQUAL
    2206              : !C         TO 1
    2207              : 
    2208            0 :       ix = 1
    2209            0 :       iy = 1
    2210            0 :       IF(incx.LT.0)ix = (-n+1)*incx + 1
    2211            0 :       IF(incy.LT.0)iy = (-n+1)*incy + 1
    2212            0 :       DO 10 i = 1,n
    2213            0 :         dtemp = c*dx(ix) + s*dy(iy)
    2214            0 :         dy(iy) = c*dy(iy) - s*dx(ix)
    2215            0 :         dx(ix) = dtemp
    2216            0 :         ix = ix + incx
    2217            0 :         iy = iy + incy
    2218            0 :    10 CONTINUE
    2219            0 :       RETURN
    2220              : 
    2221              : !C       CODE FOR BOTH INCREMENTS EQUAL TO 1
    2222              : 
    2223            0 :    20 DO 30 i = 1,n
    2224            0 :         dtemp = c*dx(i) + s*dy(i)
    2225            0 :         dy(i) = c*dy(i) - s*dx(i)
    2226            0 :         dx(i) = dtemp
    2227            0 :    30 CONTINUE
    2228              :       RETURN
    2229              :       END SUBROUTINE dsrot
    2230              : 
    2231            0 :       SUBROUTINE dsrotg(da,db,c,s)
    2232              : 
    2233              : !C     CONSTRUCT GIVENS PLANE ROTATION.
    2234              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    2235              : !C                    MODIFIED 9/27/86.
    2236              : 
    2237              :       DOUBLE PRECISION da,db,c,s,roe,scale,r,z,one,ZERO
    2238              :       DATA one, ZERO /1.0d+00, 0.0d+00/
    2239              : 
    2240            0 :       roe = db
    2241            0 :       IF( ABS(da) .GT. ABS(db) ) roe = da
    2242            0 :       scale = ABS(da) + ABS(db)
    2243            0 :       IF( scale .NE. ZERO ) GO TO 10
    2244            0 :          c = one
    2245            0 :          s = ZERO
    2246            0 :          r = ZERO
    2247            0 :          GO TO 20
    2248            0 :    10 r = scale*SQRT((da/scale)**2 + (db/scale)**2)
    2249            0 :       r = SIGN(one,roe)*r
    2250            0 :       c = da/r
    2251            0 :       s = db/r
    2252            0 :    20 z = s
    2253            0 :       IF( ABS(c) .GT. ZERO .AND. ABS(c) .LE. s ) z = one/c
    2254            0 :       da = r
    2255            0 :       db = z
    2256            0 :       RETURN
    2257              :       END SUBROUTINE dsrotg
    2258              : 
    2259            0 :       SUBROUTINE  dscal_sl(n,da,dx,incx)
    2260              : 
    2261              : !C     SCALES A VECTOR BY A CONSTANT.
    2262              : !C     USES UNROLLED LOOPS FOR INCREMENT EQUAL TO ONE.
    2263              : !C     JACK DONGARRA, LINPACK, 3/11/78.
    2264              : 
    2265              :       DOUBLE PRECISION da,dx(*)
    2266              :       INTEGER i,incx,m,mp1,n,nincx
    2267              : 
    2268            0 :       IF(n.LE.0)RETURN
    2269            0 :       IF(incx.EQ.1)GO TO 20
    2270              : 
    2271              : 
    2272              : !C        CODE FOR INCREMENT NOT EQUAL TO 1
    2273              : 
    2274            0 :       nincx = n*incx
    2275            0 :       DO 10 i = 1,nincx,incx
    2276            0 :         dx(i) = da*dx(i)
    2277            0 :    10 CONTINUE
    2278            0 :       RETURN
    2279              : 
    2280              : !C        CODE FOR INCREMENT EQUAL TO 1
    2281              : 
    2282              : !C        CLEAN-UP LOOP
    2283              : 
    2284            0 :    20 m = MOD(n,5)
    2285            0 :       IF( m .EQ. 0 ) GO TO 40
    2286            0 :       DO 30 i = 1,m
    2287            0 :         dx(i) = da*dx(i)
    2288            0 :    30 CONTINUE
    2289            0 :       IF( n .LT. 5 ) RETURN
    2290            0 :    40 mp1 = m + 1
    2291            0 :       DO 50 i = mp1,n,5
    2292            0 :         dx(i) = da*dx(i)
    2293            0 :         dx(i + 1) = da*dx(i + 1)
    2294            0 :         dx(i + 2) = da*dx(i + 2)
    2295            0 :         dx(i + 3) = da*dx(i + 3)
    2296            0 :         dx(i + 4) = da*dx(i + 4)
    2297            0 :    50 CONTINUE
    2298              :       RETURN
    2299              :       END SUBROUTINE dscal_sl
    2300              : 
    2301            0 :       subroutine bound(n, x, xl, xu)
    2302              :       integer n, i
    2303              :       double precision x(n), xl(n), xu(n)
    2304            0 :       do i = 1, n
    2305              : !C        Note that xl(i) and xu(i) may be NaN to indicate no bound
    2306            0 :          if(xl(i).eq.xl(i).and.x(i) < xl(i))then
    2307            0 :             x(i) = xl(i)
    2308            0 :          else if(xu(i).eq.xu(i).and.x(i) > xu(i))then
    2309            0 :             x(i) = xu(i)
    2310              :          end if
    2311              :       end do
    2312            0 :       end subroutine bound
    2313              : 
    2314              : !----------------------------------------------------------------------
    2315              : 
    2316              : END MODULE m_slsqp
    2317              : !!***
    2318              : 
        

Generated by: LCOV version 2.3-1