# sbols.f

          SUBROUTINE SBOLS (W, MDW, MROWS, NCOLS, BL, BU, IND, IOPT, X,
         +   RNORM, MODE, RW, IW)
    C***BEGIN PROLOGUE  SBOLS
    C***PURPOSE  Solve the problem
    C                 E*X = F (in the least  squares  sense)
    C            with bounds on selected X values.
    C***LIBRARY   SLATEC
    C***CATEGORY  K1A2A, G2E, G2H1, G2H2
    C***TYPE      SINGLE PRECISION (SBOLS-S, DBOLS-D)
    C***KEYWORDS  BOUNDS, CONSTRAINTS, INEQUALITY, LEAST SQUARES, LINEAR
    C***AUTHOR  Hanson, R. J., (SNLA)
    C***DESCRIPTION
    C
    C     The user must have dimension statements of the form:
    C
    C       DIMENSION W(MDW,NCOLS+1), BL(NCOLS), BU(NCOLS),
    C      * X(NCOLS+NX), RW(5*NCOLS)
    C       INTEGER IND(NCOLS), IOPT(1+NI), IW(2*NCOLS)
    C
    C     (here NX=number of extra locations required for option 4; NX=0
    C     for no options; NX=NCOLS if this option is in use. Here NI=number
    C     of extra locations required for options 1-6; NI=0 for no
    C     options.)
    C
    C   INPUT
    C   -----
    C
    C    --------------------
    C    W(MDW,*),MROWS,NCOLS
    C    --------------------
    C     The array W(*,*) contains the matrix [E:F] on entry. The matrix
    C     [E:F] has MROWS rows and NCOLS+1 columns. This data is placed in
    C     the array W(*,*) with E occupying the first NCOLS columns and the
    C     right side vector F in column NCOLS+1. The row dimension, MDW, of
    C     the array W(*,*) must satisfy the inequality MDW .ge. MROWS.
    C     Other values of MDW are errors. The values of MROWS and NCOLS
    C     must be positive. Other values are errors. There is an exception
    C     to this when using option 1 for accumulation of blocks of
    C     equations. In that case MROWS is an OUTPUT variable ONLY, and the
    C     matrix data for [E:F] is placed in W(*,*), one block of rows at a
    C     time.  MROWS contains the number of rows in the matrix after
    C     triangularizing several blocks of equations. This is an OUTPUT
    C     parameter ONLY when option 1 is used. See IOPT(*) CONTENTS
    C     for details about option 1.
    C
    C    ------------------
    C    BL(*),BU(*),IND(*)
    C    ------------------
    C     These arrays contain the information about the bounds that the
    C     solution values are to satisfy. The value of IND(J) tells the
    C     type of bound and BL(J) and BU(J) give the explicit values for
    C     the respective upper and lower bounds.
    C
    C    1.    For IND(J)=1, require X(J) .ge. BL(J).
    C          (the value of BU(J) is not used.)
    C    2.    For IND(J)=2, require X(J) .le. BU(J).
    C          (the value of BL(J) is not used.)
    C    3.    For IND(J)=3, require X(J) .ge. BL(J) and
    C                                X(J) .le. BU(J).
    C    4.    For IND(J)=4, no bounds on X(J) are required.
    C          (the values of BL(J) and BU(J) are not used.)
    C
    C     Values other than 1,2,3 or 4 for IND(J) are errors. In the case
    C     IND(J)=3 (upper and lower bounds) the condition BL(J) .gt. BU(J)
    C     is an error.
    C
    C    -------
    C    IOPT(*)
    C    -------
    C     This is the array where the user can specify nonstandard options
    C     for SBOLSM( ). Most of the time this feature can be ignored by
    C     setting the input value IOPT(1)=99. Occasionally users may have
    C     needs that require use of the following subprogram options. For
    C     details about how to use the options see below: IOPT(*) CONTENTS.
    C
    C     Option Number   Brief Statement of Purpose
    C     ------ ------   ----- --------- -- -------
    C           1         Return to user for accumulation of blocks
    C                     of least squares equations.
    C           2         Check lengths of all arrays used in the
    C                     subprogram.
    C           3         Standard scaling of the data matrix, E.
    C           4         User provides column scaling for matrix E.
    C           5         Provide option array to the low-level
    C                     subprogram SBOLSM( ).
    C           6         Move the IOPT(*) processing pointer.
    C          99         No more options to change.
    C
    C    ----
    C    X(*)
    C    ----
    C     This array is used to pass data associated with option 4. Ignore
    C     this parameter if this option is not used. Otherwise see below:
    C     IOPT(*) CONTENTS.
    C
    C    OUTPUT
    C    ------
    C
    C    ----------
    C    X(*),RNORM
    C    ----------
    C     The array X(*) contains a solution (if MODE .ge.0 or .eq.-22) for
    C     the constrained least squares problem. The value RNORM is the
    C     minimum residual vector length.
    C
    C    ----
    C    MODE
    C    ----
    C     The sign of MODE determines whether the subprogram has completed
    C     normally, or encountered an error condition or abnormal status. A
    C     value of MODE .ge. 0 signifies that the subprogram has completed
    C     normally. The value of MODE (.GE. 0) is the number of variables
    C     in an active status: not at a bound nor at the value ZERO, for
    C     the case of free variables. A negative value of MODE will be one
    C     of the cases -37,-36,...,-22, or -17,...,-2. Values .lt. -1
    C     correspond to an abnormal completion of the subprogram. To
    C     understand the abnormal completion codes see below: ERROR
    C     MESSAGES for SBOLS( ). AN approximate solution will be returned
    C     to the user only when max. iterations is reached, MODE=-22.
    C     Values for MODE=-37,...,-22 come from the low-level subprogram
    C     SBOLSM(). See the section ERROR MESSAGES for SBOLSM() in the
    C     documentation for SBOLSM().
    C
    C    -----------
    C    RW(*),IW(*)
    C    -----------
    C     These are working arrays with 5*NCOLS and 2*NCOLS entries.
    C     (normally the user can ignore the contents of these arrays,
    C     but they must be dimensioned properly.)
    C
    C    IOPT(*) CONTENTS
    C    ------- --------
    C     The option array allows a user to modify internal variables in
    C     the subprogram without recompiling the source code. A central
    C     goal of the initial software design was to do a good job for most
    C     people. Thus the use of options will be restricted to a select
    C     group of users. The processing of the option array proceeds as
    C     follows: a pointer, here called LP, is initially set to the value
    C     1. This value is updated as each option is processed. At the
    C     pointer position the option number is extracted and used for
    C     locating other information that allows for options to be changed.
    C     The portion of the array IOPT(*) that is used for each option is
    C     fixed; the user and the subprogram both know how many locations
    C     are needed for each option. A great deal of error checking is
    C     done by the subprogram on the contents of the option array.
    C     Nevertheless it is still possible to give the subprogram optional
    C     input that is meaningless. For example option 4 uses the
    C     locations X(NCOLS+IOFF),...,X(NCOLS+IOFF+NCOLS-1) for passing
    C     scaling data. The user must manage the allocation of these
    C     locations.
    C
    C   1
    C   -
    C     This option allows the user to solve problems with a large number
    C     of rows compared to the number of variables. The idea is that the
    C     subprogram returns to the user (perhaps many times) and receives
    C     new least squares equations from the calling program unit.
    C     Eventually the user signals "that's all" and then computes the
    C     solution with one final call to subprogram SBOLS( ). The value of
    C     MROWS is an OUTPUT variable when this option is used. Its value
    C     is always in the range 0 .le. MROWS .le. NCOLS+1. It is equal to
    C     the number of rows after the triangularization of the entire set
    C     of equations. If LP is the processing pointer for IOPT(*), the
    C     usage for the sequential processing of blocks of equations is
    C
    C        IOPT(LP)=1
    C        Move block of equations to W(*,*) starting at
    C        the first row of W(*,*).
    C        IOPT(LP+3)=# of rows in the block; user defined
    C
    C     The user now calls SBOLS( ) in a loop. The value of IOPT(LP+1)
    C     directs the user's action. The value of IOPT(LP+2) points to
    C     where the subsequent rows are to be placed in W(*,*).
    C
    C      .