C
C SPDX-License-Identifier: BSD-3-Clause
C
      SUBROUTINE BB02AD(DEF, NR, DPAR, IPAR, BPAR, CHPAR, VEC, N, M, P,
     1                  A, LDA, B, LDB, C, LDC, Q, LDQ, R, LDR, S, LDS,
     2                  X, LDX, DWORK, LDWORK, INFO)
C
C     PURPOSE
C
C     To generate the benchmark examples for the numerical solution of
C     discrete-time algebraic Riccati equations (DAREs) of the form
C
C            T                T               T    -1  T       T
C     0  =  A X A  -  X  -  (A X B + S) (R + B X B)  (B X A + S )  +  Q
C
C     as presented in [1]. Here, A,Q,X are real N-by-N matrices, B,S are
C     N-by-M, and R is M-by-M. The matrices Q and R are symmetric and Q
C     may be given in factored form
C
C                   T
C     (I)    Q  =  C Q0 C .
C
C     Here, C is P-by-N and Q0 is P-by-P. If R is nonsingular and S = 0,
C     the DARE can be rewritten equivalently as
C
C                  T             -1
C     0  =  X  -  A X (I_n + G X)  A  -  Q,
C
C     where I_n is the N-by-N identity matrix and
C
C                   -1  T
C     (II)   G = B R   B .
C
C     ARGUMENTS
C
C     Mode Parameters
C
C     DEF     CHARACTER
C             This parameter specifies if the default parameters are
C             to be used or not.
C             = 'N' or 'n' : The parameters given in the input vectors
C                            xPAR (x = 'D', 'I', 'B', 'CH') are used.
C             = 'D' or 'd' : The default parameters for the example
C                            are used.
C             This parameter is not meaningful if NR(1) = 1.
C
C     Input/Output Parameters
C
C     NR      (input) INTEGER array, dimension (2)
C             This array determines the example for which DAREX returns
C             data. NR(1) is the group of examples.
C             NR(1) = 1 : parameter-free problems of fixed size.
C             NR(1) = 2 : parameter-dependent problems of fixed size.
C             NR(1) = 3 : parameter-free problems of scalable size.
C             NR(1) = 4 : parameter-dependent problems of scalable size.
C             NR(2) is the number of the example in group NR(1).
C             Let NEXi be the number of examples in group i. Currently,
C             NEX1 = 13, NEX2 = 5, NEX3 = 0, NEX4 = 1.
C             1 <= NR(1) <= 4;
C             0 <= NR(2) <= NEXi, where i = NR(1).
C
C     DPAR    (input/output) DOUBLE PRECISION array, dimension (4)
C             Double precision parameter vector. For explanation of the
C             parameters see [1].
C             DPAR(1) defines the parameter 'epsilon' for
C             examples NR = 2.2,2.3,2.4, the parameter 'tau'
C             for NR = 2.5, and the 1-by-1 matrix R for NR = 2.1,4.1.
C             For Example 2.5, DPAR(2) - DPAR(4) define in
C             consecutive order 'D', 'K', and 'r'.
C             NOTE that DPAR is overwritten with default values
C             if DEF = 'D' or 'd'.
C
C     IPAR    (input/output) INTEGER array, dimension (3)
C             On input, IPAR(1) determines the actual state dimension,
C             i.e., the order of the matrix A as follows:
C             NR(1) = 1, NR(1) = 2   : IPAR(1) is ignored.
C             NR = NR(1).NR(2) = 4.1 : IPAR(1) determines the order of
C                                      the output matrix A.
C             NOTE that IPAR(1) is overwritten for Examples 1.1-2.3. For
C             the other examples, IPAR(1) is overwritten if the default
C             parameters are to be used.
C             On output, IPAR(1) contains the order of the matrix A.
C
C             On input, IPAR(2) is the number of colums in the matrix B
C             and the order of the matrix R (in control problems, the
C             number of inputs of the system). Currently, IPAR(2) is
C             fixed for all examples and thus is not referenced on
C             input.
C             On output, IPAR(2) is the number of columns of the
C             matrix B from (I).
C
C             On input, IPAR(3) is the number of rows in the matrix C
C             (in control problems, the number of outputs of the
C             system). Currently, IPAR(3) is fixed for all examples
C             and thus is not referenced on input.
C             On output, IPAR(3) is the number of rows of the matrix C
C             from (I).
C
C             NOTE that IPAR(2) and IPAR(3) are overwritten and
C             IPAR(2) <= IPAR(1) and IPAR(3) <= IPAR(1) for all
C             examples.
C
C     BPAR    (input) LOGICAL array, dimension (7)
C             This array defines the form of the output of the examples
C             and the storage mode of the matrices Q, G or R.
C             BPAR(1) = .TRUE.  : Q is returned.
C             BPAR(1) = .FALSE. : Q is returned in factored form, i.e.,
C                                 Q0 and C from (I) are returned.
C             BPAR(2) = .TRUE.  : The matrix returned in array Q (i.e.,
C                                 Q if BPAR(1) = .TRUE. and Q0 if
C                                 BPAR(1) = .FALSE.) is stored as full
C                                 matrix.
C             BPAR(2) = .FALSE. : The matrix returned in array Q is
C                                 provided in packed storage mode.
C             BPAR(3) = .TRUE.  : If BPAR(2) = .FALSE., the matrix
C                                 returned in array Q is stored in upper
C                                 packed mode, i.e., the upper triangle
C                                 of a symmetric n-by-n matrix is stored
C                                 by columns, e.g., the matrix entry
C                                 Q(i,j) is stored in the array entry
C                                 Q(i+j*(j-1)/2) for i <= j.
C                                 Otherwise, this entry is ignored.
C             BPAR(3) = .FALSE. : If BPAR(2) = .FALSE., the matrix
C                                 returned in array Q is stored in lower
C                                 packed mode, i.e., the lower triangle
C                                 of a symmetric n-by-n matrix is stored
C                                 by columns, e.g., the matrix entry
C                                 Q(i,j) is stored in the array entry
C                                 Q(i+(2*n-j)*(j-1)/2) for j <= i.
C                                 Otherwise, this entry is ignored.
C             BPAR(4) = .TRUE.  : The product G in (II) is returned.
C             BPAR(4) = .FALSE. : G is returned in factored form, i.e.,
C                                 B and R from (II) are returned.
C             BPAR(5) = .TRUE.  : The matrix returned in array R (i.e.,
C                                 G if BPAR(4) = .TRUE. and R if
C                                 BPAR(4) = .FALSE.) is stored as full
C                                 matrix.
C             BPAR(5) = .FALSE. : The matrix returned in array R is
C                                 provided in packed storage mode.
C             BPAR(6) = .TRUE.  : If BPAR(5) = .FALSE., the matrix
C                                 returned in array R is stored in upper
C                                 packed mode (see above).
C                                 Otherwise, this entry is ignored.
C             BPAR(6) = .FALSE. : If BPAR(5) = .FALSE., the matrix
C                                 returned in array R is stored in lower
C                                 packed mode (see above).
C                                 Otherwise, this entry is ignored.
C             BPAR(7) = .TRUE.  : The coefficient matrix S of the DARE
C                                 is returned in array S.
C             BPAR(7) = .FALSE. : The coefficient matrix S of the DARE
C                                 is not returned.
C             NOTE that there are no default values for BPAR.  If all
C             entries are declared to be .TRUE., then matrices Q, G or R
C             are returned in conventional storage mode, i.e., as
C             N-by-N or M-by-M arrays where the array element Z(I,J)
C             contains the matrix entry Z_{i,j}.
C
C     CHPAR   (output) CHARACTER*255
C             On output, this string contains short information about
C             the chosen example.
C
C     VEC     (output) LOGICAL array, dimension (10)
C             Flag vector which displays the availability of the output
C             data:
C             VEC(j), j=1,2,3, refer to N, M, and P, respectively, and
C             are always .TRUE.
C             VEC(4) refers to A and is always .TRUE.
C             VEC(5) is .TRUE. if BPAR(4) = .FALSE., i.e., the factors B
C             and R from (II) are returned.
C             VEC(6) is .TRUE. if BPAR(1) = .FALSE., i.e., the factors C
C             and Q0 from (I) are returned.
C             VEC(7) refers to Q and is always .TRUE.
C             VEC(8) refers to R and is always .TRUE.
C             VEC(9) is .TRUE. if BPAR(7) = .TRUE., i.e., the matrix S
C             is returned.
C             VEC(10) refers to X and is .TRUE. if the exact solution
C             matrix is available.
C             NOTE that VEC(i) = .FALSE. for i = 1 to 10 if on exit
C             INFO .NE. 0.
C
C     N       (output) INTEGER
C             The order of the matrices A, X, G if BPAR(4) = .TRUE., and
C             Q if BPAR(1) = .TRUE.
C
C     M       (output) INTEGER
C             The number of columns in the matrix B (or the dimension of
C             the control input space of the underlying dynamical
C             system).
C
C     P       (output) INTEGER
C             The number of rows in the matrix C (or the dimension of
C             the output space of the underlying dynamical system).
C
C     A       (output) DOUBLE PRECISION array, dimension (LDA,N)
C             The leading N-by-N part of this array contains the
C             coefficient matrix A of the DARE.
C
C     LDA     INTEGER
C             The leading dimension of array A.  LDA >= N.
C
C     B       (output) DOUBLE PRECISION array, dimension (LDB,M)
C             If (BPAR(4) = .FALSE.), then the leading N-by-M part
C             of this array contains the coefficient matrix B of
C             the DARE.  Otherwise, B is used as workspace.
C
C     LDB     INTEGER
C             The leading dimension of array B.  LDB >= N.
C
C     C       (output) DOUBLE PRECISION array, dimension (LDC,N)
C             If (BPAR(1) = .FALSE.), then the leading P-by-N part
C             of this array contains the matrix C of the factored
C             form (I) of Q.  Otherwise, C is used as workspace.
C
C     LDC     INTEGER
C             The leading dimension of array C.  LDC >= P.
C
C     Q       (output) DOUBLE PRECISION array, dimension (NQ)
C             If (BPAR(1) = .TRUE.) and (BPAR(2) = .TRUE.), then
C             NQ = LDQ*N.
C             IF (BPAR(1) = .TRUE.) and (BPAR(2) = .FALSE.), then
C             NQ = N*(N+1)/2.
C             If (BPAR(1) = .FALSE.) and (BPAR(2) = .TRUE.), then
C             NQ = LDQ*P.
C             IF (BPAR(1) = .FALSE.) and (BPAR(2) = .FALSE.), then
C             NQ = P*(P+1)/2.
C             The symmetric matrix contained in array Q is stored
C             according to BPAR(2) and BPAR(3).
C
C     LDQ     INTEGER
C             If conventional storage mode is used for Q, i.e.,
C             BPAR(2) = .TRUE., then Q is stored like a 2-dimensional
C             array with leading dimension LDQ. If packed symmetric
C             storage mode is used, then LDQ is irrelevant.
C             LDQ >= N if BPAR(1) = .TRUE.;
C             LDQ >= P if BPAR(1) = .FALSE..
C
C     R       (output) DOUBLE PRECISION array, dimension (MR)
C             If (BPAR(4) = .TRUE.) and (BPAR(5) = .TRUE.), then
C             MR = LDR*N.
C             IF (BPAR(4) = .TRUE.) and (BPAR(5) = .FALSE.), then
C             MR = N*(N+1)/2.
C             If (BPAR(4) = .FALSE.) and (BPAR(5) = .TRUE.), then
C             MR = LDR*M.
C             IF (BPAR(4) = .FALSE.) and (BPAR(5) = .FALSE.), then
C             MR = M*(M+1)/2.
C             The symmetric matrix contained in array R is stored
C             according to BPAR(5) and BPAR(6).
C
C     LDR     INTEGER
C             If conventional storage mode is used for R, i.e.,
C             BPAR(5) = .TRUE., then R is stored like a 2-dimensional
C             array with leading dimension LDR. If packed symmetric
C             storage mode is used, then LDR is irrelevant.
C             LDR >= N  if BPAR(4) =  .TRUE.;
C             LDR >= M  if BPAR(4) = .FALSE..
C
C     S       (output) DOUBLE PRECISION array, dimension (LDS,M)
C             If (BPAR(7) = .TRUE.), then the leading N-by-M part of
C             this array contains the coefficient matrix S of the DARE.
C
C     LDS     INTEGER
C             The leading dimension of array S.  LDS >= 1, and
C             LDS >= N if BPAR(7) = .TRUE..
C
C     X       (output) DOUBLE PRECISION array, dimension (LDX,NX)
C             If an exact solution is available (NR = 1.1,1.3,1.4,2.1,
C             2.3,2.4,2.5,4.1), then NX = N and the leading N-by-N part
C             of this array contains the solution matrix X.
C             Otherwise, X is not referenced.
C
C     LDX     INTEGER
C             The leading dimension of array X.  LDX >= 1, and
C             LDX >= N if an exact solution is available.
C
C     Workspace
C
C     DWORK   DOUBLE PRECISION array, dimension (LDWORK)
C
C     LDWORK  INTEGER
C             The length of the array DWORK.  LDWORK >= N*N.
C
C     Error Indicator
C
C     INFO    INTEGER
C             = 0 : successful exit;
C             < 0 : if INFO = -i, the i-th argument had an illegal
C                   value;
C             = 1 : data file could not be opened or had wrong format;
C             = 2 : division by zero;
C             = 3 : G can not be computed as in (II) due to a singular R
C                   matrix. This error can only occur if
C                   BPAR(4) = .TRUE..
C
C     REFERENCES
C
C     [1] Abels, J. and Benner, P.
C         DAREX - A Collection of Benchmark Examples for Discrete-Time
C         Algebraic Riccati Equations (Version 2.0).
C         SLICOT Working Note 1999-16, November 1999. Available from
C         http://www.win.tue.nl/niconet/NIC2/reports.html.
C
C     This is an updated and extended version of
C
C     [2] Benner, P., Laub, A.J., and Mehrmann, V.
C         A Collection of Benchmark Examples for the Numerical Solution
C         of Algebraic Riccati Equations II: Discrete-Time Case.
C         Technical Report SPC 95_23, Fak. f. Mathematik,
C         TU Chemnitz-Zwickau (Germany), December 1995.
C
C     FURTHER COMMENTS
C
C     Some benchmark examples read data from the data files provided
C     with the collection.
C
C     CONTRIBUTOR
C
C     Peter Benner (Universitaet Bremen), November 25, 1999.
C
C     For questions concerning the collection or for the submission of
C     test examples, please send e-mail to benner@math.uni-bremen.de.
C
C     REVISIONS
C
C     1999, December 23 (V. Sima).
C
C     KEYWORDS
C
C     Discrete-time algebraic Riccati equation.
C
C     ******************************************************************
C
C     .. Parameters ..
C     . # of examples available , # of examples with fixed size. .
      INTEGER          NEX1, NEX2, NEX3, NEX4, NMAX
      PARAMETER        ( NEX1 = 13, NEX2 = 5, NEX3 = 0, NEX4 = 1 )
      PARAMETER        ( NMAX = 13 )
      DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOUR, FIVE
      PARAMETER        ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
     1                   THREE = 3.0D0, FOUR = 4.0D0, FIVE = 5.0D0 )
C
C     .. Scalar Arguments ..
      INTEGER          INFO, LDA, LDB, LDC, LDQ, LDR, LDS, LDWORK, LDX,
     $                 M, N, P
      CHARACTER        DEF
C
C     .. Array Arguments ..
      DOUBLE PRECISION A(LDA,*), B(LDB,*), C(LDC,*), DPAR(*), DWORK(*),
     1                 Q(*), R(*), S(LDS,*), X(LDX,*)
      INTEGER          IPAR(3), NR(2)
      CHARACTER        CHPAR*255
      LOGICAL          BPAR(7), VEC(10)
C
C     .. Local Scalars ..
      INTEGER          I, IOS, ISYMM, J, MSYMM, NSYMM, PSYMM, QDIMM,
     1                 RDIMM
      DOUBLE PRECISION ALPHA, BETA, TEMP
C
C     ..Local Arrays ..
      INTEGER          MDEF(2,NMAX), NDEF(4,NMAX), NEX(4), PDEF(2,NMAX)
      CHARACTER        IDENT*4
      CHARACTER*255    NOTES(4,NMAX)
C
C     .. External Functions ..
C     . LAPACK .
      LOGICAL          LSAME
      EXTERNAL         LSAME
C
C     .. External Subroutines ..
C     . BLAS .
      EXTERNAL         DCOPY, DGEMV, DSPMV, DSPR, DSYMM, DSYRK
C     . LAPACK .
      EXTERNAL         DLASET, DPPTRF, DPPTRI, DRSCL, XERBLA
C     . SLICOT .
      EXTERNAL         MA02DD, MA02ED
C
C     .. Intrinsic Functions ..
      INTRINSIC        SQRT
C
C     .. Data Statements ..
C     . default values for dimensions .
      DATA NEX /NEX1, NEX2, NEX3, NEX4/
      DATA (NDEF(1,I), I = 1, NEX1) /2, 2, 2, 3, 4, 4, 4, 5, 6, 9,
     1                               11, 13, 26/
      DATA (NDEF(2,I), I = 1, NEX2) /2, 2, 2, 3, 4/
      DATA (NDEF(4,I), I = 1, NEX4) /100/
      DATA (MDEF(1,I), I = 1, NEX1) /1, 2, 1, 2, 2, 2, 4, 2, 2, 3,
     1                               2, 2, 6/
      DATA (MDEF(2,I), I = 1, NEX2) /1, 2, 1, 3, 1/
      DATA (PDEF(1,I), I = 1, NEX1) /1, 2, 2, 3, 4, 4, 4, 5, 2, 2,
     1                               4, 4, 12/
      DATA (PDEF(2,I), I = 1, NEX2) /2, 2, 2, 3, 1/
C     . comments on examples .
      DATA (NOTES(1,I), I = 1, 10) /
     1'Van Dooren 1981, Ex. II: singular R matrix', 'Ionescu/Weiss 1992
     2: singular R matrix, nonzero S matrix', 'Jonckheere 1981: (A,B) co
     3ntrollable, no solution X <= 0', 'Sun 1998: R singular, Q non-defi
     4nite', 'Ackerson/Fu 1970 : satellite control problem', 'Litkouhi 1
     5983 : system with slow and fast modes', 'Lu/Lin 1993, Ex. 4.3', 'G
     6ajic/Shen 1993, Section 2.7.4: chemical plant', 'Davison/Wang 1974
     7: nonzero S matrix', 'Patnaik et al. 1980: tubular ammonia reactor
     8'/
      DATA (NOTES(1,I), I = 11, NEX1) /
     1'Sima 1996, Sec. 1.2.2: paper machine model error integrators', 'S
     2ima 1996, Ex. 2.6: paper machine model with with disturbances', 'P
     3ower plant model, Katayama et al., 1985'/
      DATA (NOTES(2,I), I = 1, NEX2) /
     1'Laub 1979, Ex. 2: uncontrollable-unobservable data', 'Laub 1979,
     2Ex. 3: increasingly ill-conditioned R-matrix', 'increasingly bad s
     3caled system as eps -> oo','Petkov et. al. 1989 : increasingly bad
     4 scaling as eps -> oo', 'Pappas et al. 1980: process control of pa
     5per machine'/
      DATA (NOTES(4,I), I = 1, NEX4) /'Pappas et al. 1980, Ex. 3'/
C
C     .. Executable Statements ..
C
      INFO = 0
      DO 1 I = 1, 10
        VEC(I) = .FALSE.
    1 CONTINUE
C
      IF (NR(1) .GE. 3) THEN
        IF (LSAME(DEF, 'D'))  IPAR(1) = NDEF(NR(1),NR(2))
        IPAR(2) = 1
        IPAR(3) = IPAR(1)
      ELSE
        IPAR(1) = NDEF(NR(1),NR(2))
        IPAR(2) = MDEF(NR(1),NR(2))
        IPAR(3) = PDEF(NR(1),NR(2))
      END IF
C
      IF ((NR(1) .GE. 2) .AND. .NOT. ((LSAME(DEF,'D')) .OR.
     $                                (LSAME(DEF,'N')))) THEN
        INFO = -1
      ELSE IF ((NR(1) .LT. 1) .OR. (NR(1) .GT. 4) .OR. (NR(2) .LT. 0)
     1    .OR. (NR(2) .GT. NEX(NR(1)))) THEN
        INFO = -2
      ELSE IF (IPAR(1) .LT. 1) THEN
        INFO = -4
      ELSE IF (IPAR(1) .GT. LDA) THEN
        INFO = -12
      ELSE IF (IPAR(1) .GT. LDB) THEN
        INFO = -14
      ELSE IF (IPAR(3) .GT. LDC) THEN
        INFO = -16
      ELSE IF (BPAR(2) .AND. (((.NOT. BPAR(1)) .AND.
     1       (IPAR(3) .GT. LDQ)) .OR. (BPAR(1) .AND.
     2       (IPAR(1) .GT. LDQ)))) THEN
        INFO = -18
      ELSE IF (BPAR(5) .AND. ((BPAR(4) .AND. (IPAR(1) .GT. LDR)) .OR.
     1         ((.NOT. BPAR(4)) .AND. (IPAR(2) .GT. LDR)))) THEN
        INFO = -20
      ELSE IF (LDS .LT. 1 .OR. (BPAR(7) .AND. (IPAR(1) .GT. LDS))) THEN
        INFO = -22
      ELSE IF (LDX .LT. 1) THEN
        INFO = -24
      ELSE IF (((NR(1) .EQ. 1) .AND. ((NR(2) .EQ. 1)   .OR.
     1          (NR(2) .EQ. 3) .OR.   (NR(2) .EQ. 4))) .OR.
     2         ((NR(1) .EQ. 2) .AND. ((NR(2). EQ. 1)   .OR.
     3          (NR(2) .GE. 3))) .OR. (NR(1) .EQ. 4)) THEN
C    .. solution X available ..
        IF (IPAR(1) .GT. LDX) THEN
          INFO = -24
        ELSE
          CALL DLASET('A', IPAR(1), IPAR(1), ZERO, ZERO, X, LDX)
        END IF
      ELSE IF (LDWORK .LT. N*N) THEN
        INFO = -26
      END IF
      IF (INFO .NE. 0)  THEN
        CALL XERBLA( 'BB02AD', -INFO )
        RETURN
      END IF
C
      NSYMM = (IPAR(1)*(IPAR(1)+1))/2
      MSYMM = (IPAR(2)*(IPAR(2)+1))/2
      PSYMM = (IPAR(3)*(IPAR(3)+1))/2
C
      CALL DLASET('A', IPAR(1), IPAR(1), ZERO, ZERO, A, LDA)
      CALL DLASET('A', IPAR(1), IPAR(2), ZERO, ZERO, B, LDB)
      CALL DLASET('A', IPAR(3), IPAR(1), ZERO, ZERO, C, LDC)
      CALL DLASET('L', PSYMM, 1, ZERO, ZERO, Q, 1)
      CALL DLASET('L', MSYMM, 1, ZERO, ZERO, R, 1)
      IF (BPAR(7))  CALL DLASET('A', IPAR(1), IPAR(2), ZERO, ZERO,
     1                          S, LDS)
C
      IF(NR(1) .EQ. 1) THEN
C
        IF (NR(2) .EQ. 1) THEN
          A(1,1) =  TWO
          A(2,1) =  ONE
          A(1,2) = -ONE
          B(1,1) =  ONE
          Q(1)   = ONE
          C(1,2) = ONE
          R(1)   = ZERO
          CALL DLASET('A', IPAR(1), IPAR(1), ZERO, ONE, X, LDX)
          IDENT  = '0000'
C
        ELSE IF (NR(2) .EQ. 2) THEN
          A(1,2) =  ONE
          A(2,2) = -ONE
          B(1,1) =  ONE
          B(2,1) =  TWO
          B(2,2) =  ONE
          R(1)   = 9.0D0
          R(2)   = THREE
          R(3)   = ONE
          CALL DLASET('A', PSYMM, 1, -FOUR, -FOUR, Q, PSYMM)
          Q(3)   = 7.0D0
          CALL DRSCL(MSYMM, 11.0D0, Q, 1)
          IF (BPAR(7)) THEN
            S(1,1) =  THREE
            S(2,1) = -ONE
            S(1,2) =  ONE
            S(2,2) =  7.0D0
          END IF
          IDENT  = '0100'
C
        ELSE IF (NR(2) .EQ. 3) THEN
          A(1,2) = ONE
          B(2,1) = ONE
          Q(1)   = ONE
          Q(2)   = TWO
          Q(3)   = FOUR
          X(1,1) = ONE
          X(2,1) = TWO
          X(1,2) = TWO
          X(2,2) = TWO + SQRT(FIVE)
          IDENT  = '0101'
C
        ELSE IF (NR(2) .EQ. 4) THEN
          A(1,2) = .1000D+00
          A(2,3) = .0100D+00
          B(1,1) = ONE
          B(3,2) = ONE
          R(3) = ONE
          Q(1) = .1D+06
          Q(4) = .1D+04
          Q(6) = -.1D+02
          X(1,1) = .1D+06
          X(2,2) = .1D+04
          IDENT = '0100'
C
        ELSE IF (((NR(2) .GE. 5) .AND. (NR(2) .LE. 8)) .OR.
     1           (NR(2) .EQ. 10) .OR. (NR(2) .EQ. 11) .OR.
     2           (NR(2) .EQ. 13)) THEN
          IF (NR(2) .LT. 10) THEN
            WRITE (CHPAR(1:11), '(A,I1,A,I1,A)')
     1                              'BB02', NR(1), '0', NR(2), '.dat'
            OPEN(1, IOSTAT = IOS, STATUS = 'OLD', FILE = CHPAR(1:11))
          ELSE
            WRITE (CHPAR(1:11), '(A,I1,I2,A)')
     1                                   'BB02', NR(1), NR(2), '.dat'
            OPEN(1, IOSTAT = IOS, STATUS = 'OLD', FILE = CHPAR(1:11))
          END IF
          IF (IOS .NE. 0) THEN
            INFO = 1
          ELSE
            IF (.NOT. (NR(2) .EQ. 13)) THEN
              DO 10  I = 1, IPAR(1)
                READ (1, FMT = *, IOSTAT = IOS) (A(I,J), J = 1, IPAR(1))
                IF (IOS .NE. 0)  INFO = 1
   10         CONTINUE
              DO 20  I = 1, IPAR(1)
                READ (1, FMT = *, IOSTAT = IOS) (B(I,J), J = 1, IPAR(2))
                IF (IOS .NE. 0)  INFO = 1
   20         CONTINUE
            END IF
            IF (NR(2) .EQ. 5) THEN
              Q(1)  =  .187D1
              Q(4)  = -.244D0
              Q(5)  =  .744D0
              Q(6)  =  .205D0
              Q(8)  =  .589D0
              Q(10) =  .1048D1
            ELSE IF (NR(2) .EQ. 6) THEN
              Q(1)  = .1D-1
              Q(5)  = .1D-1
              Q(8)  = .1D-1
              Q(10) = .1D-1
            ELSE IF (NR(2) .EQ. 7) THEN
              CALL DLASET('U', IPAR(3), IPAR(1), ONE, ONE, C, LDC)
              C(1,3) =  TWO
              C(1,4) =  FOUR
              C(2,4) =  TWO
              Q(1)   =  TWO
              Q(2)   = -ONE
              Q(5)   =  TWO
              Q(6)   = -ONE
              Q(8)   =  TWO
            ELSE IF (NR(2) .EQ. 10) THEN
              C(1,1) = ONE
              C(2,5) = ONE
              Q(1)   = 50.0D0
              Q(3)   = 50.0D0
            ELSE IF (NR(2) .EQ. 11) THEN
              A(10,10) = ONE
              A(11,11) = ONE
              C(1,6) = 15.0D0
              C(2,7) =  7.0D0
              C(2,8) = -.5357D+01
              C(2,9) = -.3943D+01
              C(3,10) = ONE
              C(4,11) = ONE
              Q(1) = 0.5D0
              Q(5) = 5.0D0
              Q(8) = 0.5D0
              Q(10) = 5.0D0
              R(1) = 400.0D0
              R(3) = 700.0D0
              IDENT = '0000'
C
            ELSE IF (NR(2) .EQ. 13) THEN
              DO 24 I = 1, IPAR(1)-6
                READ (1, FMT = *, IOSTAT = IOS)
     1                            (A(I,J), J = 1, IPAR(1)-6)
                IF (IOS .NE. 0)  INFO = 1
   24         CONTINUE
              DO 25 I = 1, IPAR(1)-6
                READ (1, FMT = *, IOSTAT = IOS)
     1                            (B(I,J), J = 1, IPAR(2))
                IF (IOS .NE. 0)  INFO = 1
   25         CONTINUE
              DO 26 I = 1, IPAR(2)
                READ (1, FMT = *, IOSTAT = IOS)
     1                             (C(I,J), J = 1, IPAR(1)-6)
                IF (IOS .NE. 0)  INFO = 1
   26         CONTINUE
              DO 27 I = 1, 6
                A(20+I,20+I) = ONE
                C(6+I,20+I)  = ONE
   27         CONTINUE
              J = 58
              DO 28 I = 7, 12
                READ (1, FMT = *, IOSTAT = IOS) Q(J)
                IF (IOS .NE. 0)  INFO = 1
                J = J + (13 - I)
   28         CONTINUE
              J = 1
              DO 29 I = 1, 6
                READ (1, FMT = *, IOSTAT = IOS) R(J)
                IF (IOS .NE. 0)  INFO = 1
                J = J + (7 - I)
   29         CONTINUE
              DO 31 I = 1, 6
                DO 30 J = 1, 20
                  A(I+20,J) = -C(I,J)
   30           CONTINUE
   31         CONTINUE
              IDENT = '0000'
            END IF
          END IF
          CLOSE(1)
          IF ((NR(2) .EQ. 5) .OR. (NR(2) .EQ. 6)) THEN
            IDENT = '0101'
          ELSE IF ((NR(2) .EQ. 7) .OR. (NR(2) .EQ. 10)) THEN
            IDENT = '0001'
          ELSE IF (NR(2) .EQ. 8) THEN
            IDENT = '0111'
          END IF
C
        ELSE IF (NR(2). EQ. 9) THEN
          A(1,2) = ONE
          A(2,3) = ONE
          A(4,5) = ONE
          A(5,6) = ONE
          B(3,1) = ONE
          B(6,2) = ONE
          C(1,1) = ONE
          C(1,2) = ONE
          C(2,4) = ONE
          C(2,5) = -ONE
          R(1)   = THREE
          R(3)   = ONE
          IF (BPAR(7)) THEN
            S(1,1) = ONE
            S(2,1) = ONE
            S(4,1) = ONE
            S(5,1) = -ONE
          END IF
          IDENT  = '0010'
        ELSE IF (NR(2) .EQ. 12) THEN
          DO 32 I = 1, 10
            A(I,I+1) = ONE
   32     CONTINUE
          A(6,7) = ZERO
          A(8,9) = ZERO
          A(12,12) = ONE
          A(13,13) = ONE
          A(12,1) = -.3318D+01
          A(13,1) = -.15484D+01
          A(6,6) = .7788D+00
          A(8,7) = -.4724D+00
          A(13,7) = .3981D+00
          A(8,8) = .13746D+01
          A(13,8) = .5113D+00
          A(13,9) = .57865D+01
          A(11,11) = .8071D+00
          B(6,1) = ONE
          B(8,2) = ONE
          C(1,1) = .3318D+01
          C(2,1) = .15484D+01
          C(2,7) = -.3981D+00
          C(2,8) = -.5113D+00
          C(2,9) = -.57865D+01
          C(3,12) = ONE
          C(4,13) = ONE
          Q(1) = 0.5D0
          Q(5) = 5.0D0
          Q(8) = 0.5D0
          Q(10) = 5.0D0
          R(1) = 400.0D0
          R(3) = 700.0D0
          IDENT = '0000'
        END IF
C
      ELSE IF (NR(1) .EQ. 2) THEN
        IF (NR(2) .EQ. 1) THEN
          IF (LSAME(DEF, 'D')) DPAR(1) = .1D+07
          A(1,1) = FOUR
          A(2,1) = -.45D1
          A(1,2) = THREE
          A(2,2) = -.35D1
          CALL DLASET('A', IPAR(1), IPAR(2), -ONE, ONE, B, LDB)
          R(1) = DPAR(1)
          Q(1)  = 9.0D0
          Q(2)  = 6.0D0
          Q(3)  = FOUR
          TEMP  = (ONE + SQRT(ONE+FOUR*DPAR(1))) / TWO
          X(1,1) = TEMP*Q(1)
          X(2,1) = TEMP*Q(2)
          X(1,2) = X(2,1)
          X(2,2) = TEMP*Q(3)
          IDENT = '0100'
C
        ELSE IF (NR(2) .EQ. 2) THEN
          IF (LSAME(DEF, 'D')) DPAR(1) = .1D+07
          IF (DPAR(1) .EQ. ZERO) THEN
            INFO = 2
          ELSE
            A(1,1) = .9512D0
            A(2,2) = .9048D0
            CALL DLASET('A', 1, IPAR(2), .4877D1, .4877D1, B, LDB)
            B(2,1) = -.11895D1
            B(2,2) = .3569D1
            R(1)   = ONE / (THREE*DPAR(1))
            R(3)   = THREE*DPAR(1)
            Q(1)   = .5D-2
            Q(3)   = .2D-1
            IDENT  = '0100'
          END IF
C
        ELSE IF (NR(2) .EQ. 3) THEN
          IF (LSAME(DEF,'D'))  DPAR(1) = .1D7
          A(1,2) = DPAR(1)
          B(2,1) = ONE
          X(1,1) = ONE
          X(2,2) = ONE + DPAR(1)*DPAR(1)
          IDENT  = '0111'
C
        ELSE IF (NR(2) .EQ. 4) THEN
          IF (LSAME(DEF,'D'))  DPAR(1) = .1D7
          A(2,2) = ONE
          A(3,3) = THREE
          R(1)   = DPAR(1)
          R(4)   = DPAR(1)
          R(6)   = DPAR(1)
C     .. set C = V ..
          TEMP   = TWO/THREE
          CALL DLASET('A', IPAR(3), IPAR(1), -TEMP, ONE - TEMP, C, LDC)
C     .. and compute A <- C' A C
          CALL DSYMM('L', 'L', IPAR(1), IPAR(1), ONE, C, LDC, A, LDA,
     1               ZERO, DWORK, IPAR(1))
          CALL DSYMM('R', 'L', IPAR(1), IPAR(1), ONE, C, LDC, DWORK,
     1               IPAR(1), ZERO, A, LDA)
          Q(1)   = DPAR(1)
          Q(4)   = DPAR(1)
          Q(6)   = DPAR(1)
          X(1,1) = DPAR(1)
          X(2,2) = DPAR(1) * (ONE + SQRT(FIVE)) / TWO
          X(3,3) = DPAR(1) * (9.0D0 + SQRT(85.0D0)) / TWO
          CALL DSYMM('L', 'L', IPAR(1), IPAR(1), ONE, C, LDC, X, LDX,
     1               ZERO, DWORK, IPAR(1))
          CALL DSYMM('R', 'L', IPAR(1), IPAR(1), ONE, C, LDC, DWORK,
     1               IPAR(1), ZERO, X, LDX)
          IDENT  = '1000'
C
        ELSE IF (NR(2) .EQ. 5) THEN
          IF (LSAME(DEF, 'D')) THEN
            DPAR(4) = .25D0
            DPAR(3) = ONE
            DPAR(2) = ONE
            DPAR(1) = .1D9
          END IF
          IF (DPAR(1) .EQ. ZERO) THEN
            INFO = 2
          ELSE
            TEMP  = DPAR(2) / DPAR(1)
            BETA  = DPAR(3) * TEMP
            ALPHA = ONE - TEMP
            A(1,1) = ALPHA
            CALL DLASET('A', IPAR(1)-1, IPAR(1)-1, ZERO, ONE, A(2,1),
     1                  LDA)
            B(1,1) = BETA
            C(1,4) = ONE
            R(1)  = DPAR(4)
            IF (BETA .EQ. ZERO) THEN
              INFO = 2
            ELSE
              CALL DLASET('A', IPAR(1), IPAR(1), ZERO, ONE, X, LDX)
              BETA   = BETA * BETA
              TEMP   = DPAR(4) * (ALPHA + ONE) * (ALPHA - ONE) + BETA
              X(1,1) = (TEMP + SQRT(TEMP*TEMP + FOUR*BETA*DPAR(4)))
              X(1,1) = X(1,1) / TWO / BETA
            END IF
            IDENT = '0010'
          END IF
        END IF
C
      ELSE IF (NR(1) .EQ. 4) THEN
        IF (NR(2) .EQ. 1) THEN
          IF (LSAME(DEF,'D'))  DPAR(1) = ONE
          CALL DLASET('A', IPAR(1)-1, IPAR(1)-1, ZERO, ONE, A(1,2), LDA)
          B(IPAR(1),1) = ONE
          R(1) = DPAR(1)
          DO 40  I = 1, IPAR(1)
            X(I,I) = DBLE(I)
   40     CONTINUE
          IDENT  = '0110'
        END IF
      END IF
C
      IF (INFO .NE. 0)  GOTO 2001
C     .. set up data in required format ..
C
      IF (BPAR(4)) THEN
C     .. G is to be returned in product form ..
        RDIMM = IPAR(1)
        IF (IDENT(4:4) .EQ. '0') THEN
C       .. invert R using Cholesky factorization, ..
          CALL DPPTRF('L', IPAR(2), R, INFO)
          IF (INFO .EQ. 0) THEN
            CALL DPPTRI('L', IPAR(2), R, INFO)
            IF (IDENT(1:1) .EQ. '0') THEN
C           .. B is not identity matrix ..
              DO 100  I = 1, IPAR(1)
                CALL DSPMV('L', IPAR(2), ONE, R, B(I,1), LDB, ZERO,
     1                     DWORK((I-1)*IPAR(1)+1), 1)
  100         CONTINUE
              CALL DGEMV('T', IPAR(2), IPAR(1), ONE, DWORK, IPAR(1),
     1                   B(1,1), LDB, ZERO, R, 1)
              ISYMM = IPAR(1) + 1
              DO 110  I = 2, IPAR(1)
                CALL DGEMV('T', IPAR(2), IPAR(1), ONE, DWORK, IPAR(1),
     1                     B(I,1), LDB, ZERO, B(1,1), LDB)
                CALL DCOPY(IPAR(1) - I + 1, B(1,I), LDB, R(ISYMM), 1)
                ISYMM = ISYMM + (IPAR(1) - I + 1)
  110         CONTINUE
            END IF
          ELSE
            IF (INFO .GT. 0)  THEN
              INFO = 3
              GOTO 2001
            END IF
          END IF
        ELSE
C       .. R = identity ..
          IF (IDENT(1:1) .EQ. '0') THEN
C         .. B not identity matrix ..
            IF (IPAR(2) .EQ. 1) THEN
              CALL DLASET('L', NSYMM, 1, ZERO, ZERO, R, 1)
              CALL DSPR('L', IPAR(1), ONE, B, 1, R)
            ELSE
              CALL DSYRK('L', 'N', IPAR(1), IPAR(2), ONE, B, LDB, ZERO,
     1                   DWORK, IPAR(1))
              CALL MA02DD('Pack', 'Lower', IPAR(1), DWORK, IPAR(1), R)
            END IF
          ELSE
C         .. B = R = identity ..
            ISYMM = 1
            DO 120  I = IPAR(1), 1, -1
              R(ISYMM) = ONE
              ISYMM = ISYMM + I
  120       CONTINUE
          END IF
        END IF
      ELSE
        RDIMM = IPAR(2)
        IF (IDENT(1:1) .EQ. '1')
     1    CALL DLASET('A', IPAR(1), IPAR(2), ZERO, ONE, B, LDB)
        IF (IDENT(4:4) .EQ. '1') THEN
          ISYMM = 1
          DO 130  I = IPAR(2), 1, -1
            R(ISYMM) = ONE
            ISYMM = ISYMM + I
  130     CONTINUE
        END IF
      END IF
C
      IF (BPAR(1)) THEN
C     .. Q is to be returned in product form ..
        QDIMM = IPAR(1)
        IF (IDENT(3:3) .EQ. '0') THEN
          IF (IDENT(2:2) .EQ. '0') THEN
C         .. C is not identity matrix ..
            DO 140  I = 1, IPAR(1)
              CALL DSPMV('L', IPAR(3), ONE, Q, C(1,I), 1, ZERO,
     1                   DWORK((I-1)*IPAR(1)+1), 1)
  140       CONTINUE
C         .. use Q(1:IPAR(1)) as workspace and compute the first column
C            of Q at the end ..
            ISYMM = IPAR(1) + 1
            DO 150  I = 2, IPAR(1)
              CALL DGEMV('T', IPAR(3), IPAR(1), ONE, DWORK, IPAR(1),
     1                   C(1,I), 1, ZERO, Q(1), 1)
              CALL DCOPY(IPAR(1) - I + 1, Q(I), 1, Q(ISYMM), 1)
              ISYMM = ISYMM + (IPAR(1) - I + 1)
  150       CONTINUE
            CALL DGEMV('T', IPAR(3), IPAR(1), ONE, DWORK, IPAR(1),
     1                 C(1,1), 1, ZERO, Q, 1)
          END IF
        ELSE
C       .. Q = identity ..
          IF (IDENT(2:2) .EQ. '0') THEN
C         .. C is not identity matrix ..
            IF (IPAR(3) .EQ. 1) THEN
              CALL DLASET('L', NSYMM, 1, ZERO, ZERO, Q, 1)
              CALL DSPR('L', IPAR(1), ONE, C, LDC, Q)
            ELSE
              CALL DSYRK('L', 'T', IPAR(1), IPAR(3), ONE, C, LDC, ZERO,
     1                   DWORK, IPAR(1))
              CALL MA02DD('Pack', 'Lower', IPAR(1), DWORK, IPAR(1), Q)
            END IF
          ELSE
C         .. C = Q = identity ..
            ISYMM = 1
            DO 160  I = IPAR(1), 1, -1
              Q(ISYMM) = ONE
              ISYMM    = ISYMM + I
  160       CONTINUE
          END IF
        END IF
      ELSE
        QDIMM = IPAR(3)
        IF (IDENT(2:2) .EQ. '1')
     1    CALL DLASET('A', IPAR(3), IPAR(1), ZERO, ONE, C, LDC)
        IF (IDENT(3:3) .EQ. '1') THEN
          ISYMM = 1
          DO 170  I = IPAR(3), 1, -1
            Q(ISYMM) = ONE
            ISYMM    = ISYMM + I
  170     CONTINUE
        END IF
      END IF
C
C     .. unpack symmetric matrices if required ..
      IF (BPAR(2)) THEN
        ISYMM = (QDIMM * (QDIMM + 1)) / 2
        CALL DCOPY(ISYMM, Q, 1, DWORK, 1)
        CALL MA02DD('Unpack', 'Lower', QDIMM, Q, LDQ, DWORK)
        CALL MA02ED('Lower', QDIMM, Q, LDQ)
      ELSE IF (BPAR(3)) THEN
        CALL MA02DD('Unpack', 'Lower', QDIMM, DWORK, QDIMM, Q)
        CALL MA02ED('Lower', QDIMM, DWORK, QDIMM)
        CALL MA02DD('Pack', 'Upper', QDIMM, DWORK, QDIMM, Q)
      END IF
      IF (BPAR(5)) THEN
        ISYMM = (RDIMM * (RDIMM + 1)) / 2
        CALL DCOPY(ISYMM, R, 1, DWORK, 1)
        CALL MA02DD('Unpack', 'Lower', RDIMM, R, LDR, DWORK)
        CALL MA02ED('Lower', RDIMM, R, LDR)
      ELSE IF (BPAR(6)) THEN
        CALL MA02DD('Unpack', 'Lower', RDIMM, DWORK, RDIMM, R)
        CALL MA02ED('Lower', RDIMM, DWORK, RDIMM)
        CALL MA02DD('Pack', 'Upper', RDIMM, DWORK, RDIMM, R)
      END IF
C
C     ...set VEC...
      VEC(1) = .TRUE.
      VEC(2) = .TRUE.
      VEC(3) = .TRUE.
      VEC(4) = .TRUE.
      VEC(5) = .NOT. BPAR(4)
      VEC(6) = .NOT. BPAR(1)
      VEC(7) = .TRUE.
      VEC(8) = .TRUE.
      VEC(9) = BPAR(7)
      IF (((NR(1) .EQ. 1) .AND. ((NR(2) .EQ. 1)   .OR.
     1     (NR(2) .EQ. 3) .OR.   (NR(2) .EQ. 4))) .OR.
     2    ((NR(1) .EQ. 2) .AND. ((NR(2). EQ. 1)   .OR.
     3     (NR(2) .GE. 3))) .OR. (NR(1) .EQ. 4)) THEN
        VEC(10) = .TRUE.
      END IF
      CHPAR = NOTES(NR(1),NR(2))
      N = IPAR(1)
      M = IPAR(2)
      P = IPAR(3)
C
 2001 CONTINUE
      RETURN
C *** Last line of BB02AD ***
      END
