#
# Double type LAPACK routines:  Simple and Divide and Conquer Driver
#				Routines for Standard Eigenvalue and
#				Singular Value Problems
#
# This file includes problem specifications for the following:
#
# DGESVD
# DGESDD
# DGEEV
# DSTEVD
# DSTEVX
# DSTEVR
# DSTEV
# DSBEVD
# DSBEVX
# DSBEV
# DSYEVD
# DSYEVX
# DSYEVR
# DSYEV

#
# DGESVD
#
@PROBLEM dgesvd
@FUNCTION dgesvd
@LIB $(LAPACK_LIB_LINK)
@LIB $(BLAS_LIB_LINK)
#@LIB -xlic_lib=sunperf
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Eig_and_Singular/
@DESCRIPTION
DGESVD computes the singular value decomposition (SVD) of a real
M-by-N matrix A, optionally computing the left and/or right singular
vectors. The SVD is written

     A = U * SIGMA * transpose(V)

where SIGMA is an M-by-N matrix which is zero except for its
min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
are the singular values of A; they are real and non-negative, and
are returned in descending order.  The first min(m,n) columns of
U and V are the left and right singular vectors of A.

Note that the routine returns V**T, not V.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobu
JOBU    (input) CHARACTER*1
        Specifies options for computing all or part of the matrix U:
        = 'A':  all M columns of U are returned in array U:
        = 'S':  the first min(m,n) columns of U (the left singular
                vectors) are returned in the array U;
        = 'O':  the first min(m,n) columns of U (the left singular
                vectors) are overwritten on the array A;
        = 'N':  no columns of U (no left singular vectors) are
                computed.
@OBJECT SCALAR CHAR jobvt
JOBVT   (input) CHARACTER*1
        Specifies options for computing all or part of the matrix
        V**T:
        = 'A':  all N rows of V**T are returned in the array VT;
        = 'S':  the first min(m,n) rows of V**T (the right singular
                vectors) are returned in the array VT;
        = 'O':  the first min(m,n) rows of V**T (the right singular
                vectors) are overwritten on the array A;
        = 'N':  no rows of V**T (no right singular vectors) are
                computed.

        JOBVT and JOBU cannot both be 'O'.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OUTPUT 5
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit,
        if JOBU = 'O',  A is overwritten with the first min(m,n)
                        columns of U (the left singular vectors,
                        stored columnwise);
        if JOBVT = 'O', A is overwritten with the first min(m,n)
                        rows of V**T (the right singular vectors,
                        stored rowwise);
        if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A
                        are destroyed.
@OBJECT VECTOR D s
S       (output) DOUBLE PRECISION array, dimension (min(M,N))
        The singular values of A, sorted so that S(i) >= S(i+1).
@OBJECT MATRIX D u
U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
        (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
        If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
        if JOBU = 'S', U contains the first min(m,n) columns of U
        (the left singular vectors, stored columnwise);
        if JOBU = 'N' or 'O', U is not referenced.
@OBJECT MATRIX D vt
VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
        If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
        V**T;
        if JOBVT = 'S', VT contains the first min(m,n) rows of
        V**T (the right singular vectors, stored rowwise);
        if JOBVT = 'N' or 'O', VT is not referenced.

@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit.
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  if DBDSQR did not converge, INFO specifies how many
              superdiagonals of an intermediate bidiagonal form B
              did not converge to zero. See the description of WORK
              above for details.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG mI2
@ARG nI2
@ARG I2,O0
@ARG lI2,lO0
@ARG O1
@ARG O2
@ARG lO2
@ARG O3
@ARG lO3
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dgesvd(char *jobu, char *jobvt, int *m, int *n, double *a,
                   int *lda, double *s, double *u, int *ldu, double *vt,
                   int *ldvt, double *work, int *lwork, int *info);

int lda, ldu, ldvt, lwork, minmn, maxmn, scratcha, scratchb;
double *work;

if (*@I0@ == 'a' || *@I0@ == 'A')
   *@I0@ = 'A';
else if (*@I0@ == 's' || *@I0@ == 'S')
   *@I0@ = 'S';
else if (*@I0@ == 'o' || *@I0@ == 'O')
   *@I0@ = 'O';
else if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 's' || *@I1@ == 'S')
   *@I1@ = 'S';
else if (*@I1@ == 'o' || *@I1@ == 'O')
   *@I1@ = 'O';
else if (*@I1@ == 'n' || *@I1@ == 'N')
   *@I1@ = 'N';
else 
   return NS_PROT_BAD_VALUES;

if (*@I0@ == 'O' && *@I1@ == 'O') 
   return NS_PROT_BAD_VALUES; 


lda = (*@mI2@ > 1) ? *@mI2@ : 1;

minmn = (*@nI2@ < *@mI2@) ? *@nI2@ : *@mI2@;
maxmn = (*@nI2@ > *@mI2@) ? *@nI2@ : *@mI2@;

if (*@I0@ == 'A') {
   ldu = (*@mI2@ > 1) ? *@mI2@ : 1;
} else if (*@I0@ == 'S') {
   ldu = (minmn > 1) ? minmn : 1;
} else ldu = 1;

if (*@I1@ == 'A') {
   ldvt = (*@nI2@ > 1) ? *@nI2@ : 1;
} else if (*@I1@ == 'S') {
   ldvt = (minmn > 1) ? minmn : 1;
} else ldvt = 1;

scratchb = maxmn + 3 * minmn;
scratcha = 5 * minmn;
scratcha = (scratcha > scratchb) ? scratcha : scratchb;
lwork = (scratcha > 1) ? scratcha : 1;

work = (double *) malloc(sizeof(double) * lwork);
@O1@ = (double *) malloc(sizeof(double) * minmn);
*@mO1@ = minmn;
if (*@I0@ == 'A') {
   @O2@ = (double *) malloc(sizeof(double) * ldu * *@mI2@);
   *@mO2@ = ldu;
   *@nO2@ = *@mI2@;
} else if (*@I0@ == 'S') {
   @O2@ = (double *) malloc(sizeof(double) * ldu * minmn);
   *@mO2@ = ldu;
   *@nO2@ = minmn;
} else {
   @O2@ = (double *) malloc(sizeof(double));
   *@mO2@ = 1;
   *@nO2@ = 1;
}

if (*@I0@ == 'A') {
   @O3@ = (double *) malloc(sizeof(double) * *@nI2@ * ldvt);
   *@mO3@ = ldvt;
   *@nO3@ = *@nI2@;
} else if (*@I0@ == 'S') {
   @O3@ = (double *) malloc(sizeof(double) * minmn * ldvt);
   *@mO3@ = ldvt;
   *@nO3@ = minmn;
} else {
   @O3@ = (double *) malloc(sizeof(double));
   *@mO3@ = 1;
   *@nO3@ = 1;
}
@O4@ = (int *) malloc(sizeof(int));

dgesvd(@I0@, @I1@, @mI2@, @nI2@, @I2@, &lda,
       @O1@, @O2@, &ldu, @O3@, &ldvt, work, &lwork, @O4@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

@END_CODE
#
# DGESDD
#
@PROBLEM dgesdd
@FUNCTION dgesdd
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/DivideandConquer/Eig_and_Singular/
@DESCRIPTION
DGESDD computes the singular value decomposition (SVD) of a real
M-by-N matrix A, optionally computing the left and/or right singular
vectors. The SVD is written

     A = U * SIGMA * transpose(V)

where SIGMA is an M-by-N matrix which is zero except for its
min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
are the singular values of A; they are real and non-negative, and
are returned in descending order.  The first min(m,n) columns of
U and V are the left and right singular vectors of A.

Note that the routine returns V**T, not V.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 2
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        Specifies options for computing all or part of the matrix U:
        = 'A':  all M columns of U and all N rows of V**T are
                returned in the arrays U and VT;
        = 'S':  the first min(M,N) columns of U and the first
                min(M,N) rows of V**T are returned in the arrays U
                and VT;
        = 'O':  If M >= N, the first N columns of U are overwritten
                on the array A and all rows of V**T are returned in
                the array VT;
                otherwise, all columns of U are returned in the
                array U and the first M rows of V**T are overwritten
                in the array VT;
        = 'N':  no columns of U or rows of V**T are computed.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OUTPUT 5
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit,
        if JOBZ = 'O',  A is overwritten with the first min(m,n)
                        columns of U (the left singular vectors,
                        stored columnwise);
                        A is overwritten with the first min(m,n)
                        rows of V**T (the right singular vectors,
                        stored rowwise);
        if JOBZ .ne. 'O', the contents of A are destroyed.
@OBJECT VECTOR D s
S       (output) DOUBLE PRECISION array, dimension (min(M,N))
        The singular values of A, sorted so that S(i) >= S(i+1).
@OBJECT MATRIX D u
U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
        UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
        UCOL = min(M,N) if JOBZ = 'S'.
        If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
        orthogonal matrix U;
        if JOBZ = 'S', U contains the first min(M,N) columns of U
        (the left singular vectors, stored columnwise);
        if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
@OBJECT MATRIX D vt
VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
       If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
       N-by-N orthogonal matrix V**T;
       if JOBZ = 'S', VT contains the first min(M,N) rows of
       V**T (the right singular vectors, stored rowwise);
       if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit.
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  if DBDSDC did not converge, updating process failed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG mI1
@ARG nI1
@ARG I1,O0
@ARG lI1,lO0
@ARG O1
@ARG O2
@ARG lO2
@ARG O3
@ARG lO3
@ARG ?
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dgesdd(char *jobz, int *m, int *n, double *a, int *lda,
                   double *s, double *u, int *ldu, double *vt, int *ldvt,
                   double *work, int *lwork, int *iwork, int *info);

int lda, ldu, ldvt, lwork, minmn, maxmn;
int smlsiz;
/*
int zero = 0;
int nine = 9;
*/
double *work;
int *iwork;

/*
extern int ilaenv();
*/

if (*@I0@ == 'a' || *@I0@ == 'A')
   *@I0@ = 'A';
else if (*@I0@ == 's' || *@I0@ == 'S')
   *@I0@ = 'S';
else if (*@I0@ == 'o' || *@I0@ == 'O')
   *@I0@ = 'O';
else if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else
   return NS_PROT_BAD_VALUES;

lda = (*@mI1@ > 1) ? *@mI1@ : 1;
if (*@I0@ == 'S' || *@I0@ == 'A' || *@I0@ == 'O' ) {
   ldu = (*@mI1@ > 1) ? *@mI1@ : 1;
} else ldu = 1;

minmn = (*@nI1@ < *@mI1@) ? *@nI1@ : *@mI1@;
maxmn = (*@nI1@ > *@mI1@) ? *@nI1@ : *@mI1@;

switch (*@I0@) {
    case 'N' : smlsiz = 25;
         /*      smlsiz = ilaenv(&nine, "dgesdd", " ", &zero, &zero, &zero,
                               &zero ); */
               lwork = ( 14*minmn+4 > 10*minmn+2+smlsiz*(smlsiz+8) )
                       ? 14*minmn+4 : 10*minmn+2+smlsiz*(smlsiz+8); 
               lwork += maxmn;
               ldvt = 1;
    case 'O' : ldvt = *@nI1@;
               lwork = 5*minmn*minmn+maxmn+9*minmn;
    case 'A' : ldvt = *@nI1@;
               lwork = 4*minmn*minmn+maxmn+9*minmn;
               break;
    case 'S' : ldvt =  minmn;
               lwork = 4*minmn*minmn+maxmn+9*minmn;
               break;
    default  : ldvt = 1;
}

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * 8 * minmn);

if (ldvt < 1) ldvt = 1;

@O1@ = (double *) malloc(sizeof(double) * minmn);
*@mO1@ = minmn;
if (*@I0@ == 'A' || *@I0@ == 'O') {
   @O2@ = (double *) malloc(sizeof(double) * ldu * *@mI1@);
   *@mO2@ = ldu;
   *@nO2@ = *@mI1@;
} else if (*@I0@ == 'S') {
   @O2@ = (double *) malloc(sizeof(double) * ldu * minmn);
   *@mO2@ = ldu;
   *@nO2@ = minmn;
} else {
   @O2@ = (double *) malloc(sizeof(double));
   *@mO2@ = 1;
   *@nO2@ = 1;
}

if (*@I0@ == 'A' || *@I0@ == 'O' || *@I0@ == 'S') {
   @O3@ = (double *) malloc(sizeof(double) * *@nI1@ * ldvt);
   *@mO3@ = ldvt;
   *@nO3@ = *@nI1@;
} else {
   @O3@ = (double *) malloc(sizeof(double));
   *@mO3@ = 1;
   *@nO3@ = 1;
}
@O4@ = (int *) malloc(sizeof(int));

dgesdd(@I0@, @mI1@, @nI1@, @I1@, &lda,
       @O1@, @O2@, &ldu, @O3@, &ldvt, work, &lwork, iwork, @O4@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

@END_CODE
#
# DGEEV
#
@PROBLEM dgeev
@FUNCTION dgeev
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Eig_and_Singular/
@DESCRIPTION
DGEEV computes for an N-by-N real nonsymmetric matrix A, the
eigenvalues and, optionally, the left and/or right eigenvectors.

The right eigenvector v(j) of A satisfies
                 A * v(j) = lambda(j) * v(j)
where lambda(j) is its eigenvalue.
The left eigenvector u(j) of A satisfies
              u(j)**H * A = lambda(j) * u(j)**H
where u(j)**H denotes the conjugate transpose of u(j).

The computed eigenvectors are normalized to have Euclidean norm
equal to 1 and largest component real.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobvl
JOBVL   (input) CHARACTER*1
        = 'N': left eigenvectors of A are not computed;
        = 'V': left eigenvectors of A are computed.
@OBJECT SCALAR CHAR jobvr
JOBVR   (input) CHARACTER*1
        = 'N': right eigenvectors of A are not computed;
        = 'V': right eigenvectors of A are computed.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the N-by-N matrix A.
@OUTPUT 6
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, A has been overwritten.
@OBJECT VECTOR D wr
WR      (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D wi
WI      (output) DOUBLE PRECISION array, dimension (N)
        WR and WI contain the real and imaginary parts,
        respectively, of the computed eigenvalues.  Complex
        conjugate pairs of eigenvalues appear consecutively
        with the eigenvalue having the positive imaginary part
        first.
@OBJECT MATRIX D vl
VL      (output) DOUBLE PRECISION array, dimension (LDVL,N)
        If JOBVL = 'V', the left eigenvectors u(j) are stored one
        after another in the columns of VL, in the same order
        as their eigenvalues.
        If JOBVL = 'N', VL is not referenced.
        If the j-th eigenvalue is real, then u(j) = VL(:,j),
        the j-th column of VL.
        If the j-th and (j+1)-st eigenvalues form a complex
        conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and
        u(j+1) = VL(:,j) - i*VL(:,j+1).
@OBJECT MATRIX D vr
VR      (output) DOUBLE PRECISION array, dimension (LDVR,N)
        If JOBVR = 'V', the right eigenvectors v(j) are stored one
        after another in the columns of VR, in the same order
        as their eigenvalues.
        If JOBVR = 'N', VR is not referenced.
        If the j-th eigenvalue is real, then v(j) = VR(:,j),
        the j-th column of VR.
        If the j-th and (j+1)-st eigenvalues form a complex
        conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and
        v(j+1) = VR(:,j) - i*VR(:,j+1).
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  if INFO = i, the QR algorithm failed to compute all the
              eigenvalues, and no eigenvectors have been computed;
              elements i+1:N of WR and WI contain eigenvalues which
              have converged.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# char, jobvl
@ARG I0
# char, jobvr
@ARG I1
# int, N, size of A
@ARG nI2,mI2
# A, matrix (LDA, N)
@ARG I2,O0
# LDA
@ARG lI2,lO0
# WR, (N)
@ARG O1
# WI (N)
@ARG O2
# VL (LDVL, N)
@ARG O3
# LDVL
@ARG lO3
# VR (LDVR, N)
@ARG O4
# LDVR
@ARG lO4
# work
@ARG ?
# lwork
@ARG ?
# INFO
@ARG O5
@CODE
extern void dgeev(char *jobvl, char *jobvr, int *n, double *a, int *lda,
                  double *wr, double *wi, double *vl, int *ldvl, double *vr, 
                  int *ldvr, double *work, int *lwork, int *info);

int lda, ldvl = 1, ldvr = 1, lwork;
int mvl, mvr;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N') 
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V') 
   *@I0@ = 'V';
else
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N') 
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V') 
   *@I1@ = 'V';
else
   return NS_PROT_BAD_VALUES;

if (*@mI2@ != *@nI2@) return NS_PROT_DIM_MISMATCH;

lda = (*@nI2@ > 1) ? *@nI2@ : 1;
if (*@I0@ == 'V') {
    ldvl = (*@nI2@ > 1) ? *@nI2@ : 1;
} 
if (*@I1@ == 'V') {
    ldvr = (*@nI2@ > 1) ? *@nI2@ : 1;
}

if (*@I0@ == 'V' || *@I1@ == 'V')
  lwork = 4 * (*@mI2@);
else
  lwork = 3 * (*@mI2@);
if (lwork < 1)
  lwork = 1;
work = (double *) malloc(sizeof(double) * lwork);

if (*@I0@ == 'V') {
   mvl =  (*@mI2@ > 1) ? *@mI2@ : 1;
} else {
   mvl = 1;
}

if (*@I1@ == 'V') {
   mvr = (*@mI2@ > 1) ? *@mI2@ : 1;
} else {
   mvr = 1;
}

@O1@ = (double *) malloc(sizeof(double) * *@mI2@);
@O2@ = (double *) malloc(sizeof(double) * *@mI2@);
@O3@ = (double *) malloc(sizeof(double) * mvl * ldvl);
@O4@ = (double *) malloc(sizeof(double) * mvr * ldvr);
@O5@ = (int *) malloc(sizeof(int));

dgeev(@I0@, @I1@, @nI2@, @I2@, &lda, @O1@, @O2@, @O3@, &ldvl,
      @O4@, &ldvr, work, &lwork, @O5@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@mI2@;

*@mO1@ = *@mI2@;
*@mO2@ = *@mI2@;

*@mO3@ = ldvl;
*@nO3@ = mvl;

*@mO4@ = ldvr;
*@nO4@ = mvr;

@END_CODE

#
# DSTEVD
#
@PROBLEM dstevd
@FUNCTION dstevd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/DivideandConquer/Eig_and_Singular/
@DESCRIPTION
*  DSTEVD computes all eigenvalues and, optionally, eigenvectors of a
*  real symmetric tridiagonal matrix. If eigenvectors are desired, it
*  uses a divide and conquer algorithm.
*
*  The divide and conquer algorithm makes very mild assumptions about
*  floating point arithmetic. It will work on machines with a guard
*  digit in add/subtract, or on those binary machines without guard
*  digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
*  Cray-2. It could conceivably fail on hexadecimal or decimal machines
*  without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the n diagonal elements of the tridiagonal matrix
        A.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the (n-1) subdiagonal elements of the tridiagonal
        matrix A, stored in elements 1 to N-1 of E; E(N) need not
        be set, but is used by the routine.
@OUTPUT 4
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, if INFO = 0, the eigenvalues in ascending order.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, the contents of E are destroyed.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
        eigenvectors of the matrix A, with the i-th column of Z
        holding the eigenvector associated with D(i).
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of E did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG mI1,mI2
@ARG I1,O0
@ARG I2,O1
@ARG O2
@ARG lO2
@ARG ?
@ARG ?
@ARG ?
@ARG ?
@ARG O3
@CODE
extern void dstevd(char *jobz, int *n, double *d, double *e, double *z,
                   int *ldz, double *work, int *lwork, int *iwork,
                   int *liwork, int *info);

int ldz, lwork, liwork, *iwork;
double *work;

if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else
   return NS_PROT_BAD_VALUES;

if (*@I0@ == 'V') {
   ldz = (*@mI1@ > 1) ? *@mI1@ : 1;
} else ldz = 1;

lwork = 1 + 4 * *@mI1@ + *@mI1@ * *@mI1@;
work = (double *) malloc(sizeof(double) * lwork);
liwork = 3 + 5 * *@mI1@;
iwork = (int *) malloc(sizeof(int) * liwork);
@O2@ = (double *) malloc(sizeof(double) * ldz * *@mI1@);
@O3@ = (int *) malloc(sizeof(int));

dstevd(@I0@, @mI1@, @I1@, @I2@, @O2@, &ldz,
       work, &lwork, iwork, &liwork, @O3@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;

@O1@ = @I2@;
*@mO1@ = *@mI2@;

*@mO2@ = ldz;
*@nO2@ = *@mI1@;
@END_CODE

#
# DSTEVX
#
@PROBLEM dstevx
@FUNCTION dstevx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Expert/Eig_and_Singular/
@DESCRIPTION
DSTEVX computes selected eigenvalues and, optionally, eigenvectors
of a real symmetric tridiagonal matrix A.  Eigenvalues and
eigenvectors can be selected by specifying either a range of values
or a range of indices for the desired eigenvalues.
http://www.netlib.org/lapack/
@INPUT 9
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the n diagonal elements of the tridiagonal matrix A.
        On exit, D may be multiplied by a constant factor chosen
        to avoid over/underflow in computing the eigenvalues.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the (n-1) subdiagonal elements of the tridiagonal
        matrix A in elements 1 to N-1 of E; E(N) need not be set.
        On exit, E may be multiplied by a constant factor chosen
        to avoid over/underflow in computing the eigenvalues.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        Eigenvalues will be computed most accurately when ABSTOL is
        set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        If this routine returns with INFO>0, indicating that some
        eigenvectors did not converge, try setting ABSTOL to
        2*DLAMCH('S').

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.
@OUTPUT 5
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        If an eigenvector fails to converge, then that column of Z
        contains the latest approximation to the eigenvector, and the
        index of the eigenvector is returned in IFAIL.
        If JOBZ = 'N', then Z is not referenced.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I ifail
IFAIL   (output) INTEGER array, dimension (N)
        If JOBZ = 'V', then if INFO = 0, the first M elements of
        IFAIL are zero.  If INFO > 0, then IFAIL contains the
        indices of the eigenvectors that failed to converge.
        If JOBZ = 'N', then IFAIL is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, then i eigenvectors failed to converge.
              Their indices are stored in array IFAIL.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG mI2,mI3
@ARG I2
@ARG I3
@ARG I4
@ARG I5
@ARG I6
@ARG I7
@ARG I8
@ARG O0
@ARG O1
@ARG O2
@ARG lO2
@ARG ?
@ARG ?
@ARG O3
@ARG O4
@CODE
extern void dstevx(char *jobz, char *range, int *n, double *d, double *e,
                   double *vl, double *vu, int *il, int *iu, double *abstol,
                   int *m, double *w, double *z, int *ldz, double *work,
                   int *iwork, int *ifail, int *info);

int ldz, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

ldz = (*@mI2@ > 1) ? *@mI2@ : 1;

liwork = (5 * *@mI2@ > 1) ? 5 * *@mI2@ : 1;
lwork = (5 * *@mI2@ > 1) ? 5 * *@mI2@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O0@ = (int *) malloc(sizeof(int));
@O1@ = (double *) malloc(sizeof(double) * *@mI2@);
@O2@ = (double *) malloc(sizeof(double) * ldz * *@mI2@);
@O3@ = (int *) malloc(sizeof(int) * *@mI2@);
@O4@ = (int *) malloc(sizeof(int));

dstevx(@I0@, @I1@, @mI2@, @I2@, @I3@, @I4@, @I5@,
       @I6@, @I7@, @I8@, @O0@, @O1@, @O2@, &ldz, work,
       iwork, @O3@, @O4@);

*@mO1@ = *@mI2@;

*@mO2@ = *@mI2@;
*@nO2@ = *@mI2@;

*@mO3@ = 2 * *@mI2@;
@END_CODE

#
# DSTEVR
#
@PROBLEM dstevr
@FUNCTION dstevr
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/RRR/Eig_and_Singular/
@DESCRIPTION
*  DSTEVR computes selected eigenvalues and, optionally, eigenvectors
*  of a real symmetric tridiagonal matrix T.  Eigenvalues and
*  eigenvectors can be selected by specifying either a range of values
*  or a range of indices for the desired eigenvalues.
*
*  Whenever possible, DSTEVR calls SSTEGR to compute the
*  eigenspectrum using Relatively Robust Representations.  DSTEGR
*  computes eigenvalues by the dqds algorithm, while orthogonal
*  eigenvectors are computed from various "good" L D L^T representations
*  (also known as Relatively Robust Representations). Gram-Schmidt
*  orthogonalization is avoided as far as possible. More specifically,
*  the various steps of the algorithm are as follows. For the i-th
*  unreduced block of T,
*     (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T
*          is a relatively robust representation,
*     (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high
*         relative accuracy by the dqds algorithm,
*     (c) If there is a cluster of close eigenvalues, "choose" sigma_i
*         close to the cluster, and go to step (a),
*     (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T,
*         compute the corresponding eigenvector by forming a
*         rank-revealing twisted factorization.
*  The desired accuracy of the output can be specified by the input
*  parameter ABSTOL.
*
*  For more details, see "A new O(n^2) algorithm for the symmetric
*  tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon,
*  Computer Science Division Technical Report No. UCB//CSD-97-971,
*  UC Berkeley, May 1997.
*
*
*  Note 1 : DSTEVR calls SSTEGR when the full spectrum is requested
*  on machines which conform to the ieee-754 floating point standard.
*  DSTEVR calls SSTEBZ and SSTEIN on non-ieee machines and
*  when partial spectrum requests are made.
*
*  Normal execution of DSTEGR may create NaNs and infinities and
*  hence may abort due to a floating point exception in environments
*  which do not handle NaNs and infinities in the ieee standard default
*  manner.
http://www.netlib.org/lapack/
@INPUT 9
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and
********** DSTEIN are called
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the n diagonal elements of the tridiagonal matrix A.
        On exit, D may be multiplied by a constant factor chosen
        to avoid over/underflow in computing the eigenvalues.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the (n-1) subdiagonal elements of the tridiagonal
        matrix A in elements 1 to N-1 of E; E(N) need not be set.
        On exit, E may be multiplied by a constant factor chosen
        to avoid over/underflow in computing the eigenvalues.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.

        If high relative accuracy is important, set ABSTOL to
        DLAMCH( 'Safe minimum' ).  Doing so will guarantee that
        eigenvalues are computed to high relative accuracy when
        possible in future releases.  The current code does not
        make any guarantees about high relative accuracy, but
        furutre releases will. See J. Barlow and J. Demmel,
        "Computing Accurate Eigensystems of Scaled Diagonally
        Dominant Matrices", LAPACK Working Note #7, for a discussion
        of which matrices define their eigenvalues to high relative
        accuracy.
@OUTPUT 5
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        If JOBZ = 'N', then Z is not referenced.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I isuppz
ISUPPZ  (output) INTEGER array, dimension ( 2*max(1,M) )
        The support of the eigenvectors in Z, i.e., the indices
        indicating the nonzero elements in Z. The i-th eigenvector
        is nonzero only in elements ISUPPZ( 2*i-1 ) through
        ISUPPZ( 2*i ).
******* Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  Internal error
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG mI2,mI3
@ARG I2
@ARG I3
@ARG I4
@ARG I5
@ARG I6
@ARG I7
@ARG I8
@ARG O0
@ARG O1
@ARG O2
@ARG lO2
@ARG O3
@ARG ?
@ARG ?
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dstevr(char *jobz, char *range, int *n, double *d, double *e,
                   double *vl, double *vu, int *il, int *iu, double *abstol,
                   int *m, double *w, double *z, int *ldz, int *isuppz,
                   double *work, int *lwork, int *iwork, int *liwork,
                   int *info);

int ldz, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

ldz = (*@mI2@ > 1) ? *@mI2@ : 1;

liwork = (10 * *@mI2@ > 1) ? 10 * *@mI2@ : 1;
lwork = (20 * *@mI2@ > 1) ? 20 * *@mI2@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O0@ = (int *) malloc(sizeof(int));
@O1@ = (double *) malloc(sizeof(double) * *@mI2@);
@O2@ = (double *) malloc(sizeof(double) * ldz * *@mI2@);
@O3@ = (int *) malloc(sizeof(int) * 2 * *@mI2@);
@O4@ = (int *) malloc(sizeof(int));

dstevr(@I0@, @I1@, @mI2@, @I2@, @I3@, @I4@, @I5@,
       @I6@, @I7@, @I8@, @O0@, @O1@, @O2@, &ldz, @O3@, work, &lwork, 
       iwork, &liwork, @O4@);

*@mO1@ = *@mI2@;

*@mO2@ = *@mI2@;
*@nO2@ = *@mI2@;

*@mO3@ = 2 * *@mI2@;
@END_CODE


#
# DSTEV
#
@PROBLEM dstev
@FUNCTION dstev
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Eig_and_Singular/
@DESCRIPTION
DSTEV computes all eigenvalues and, optionally, eigenvectors of a
real symmetric tridiagonal matrix A.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the n diagonal elements of the tridiagonal matrix
        A.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the (n-1) subdiagonal elements of the tridiagonal
        matrix A, stored in elements 1 to N-1 of E; E(N) need not
        be set, but is used by the routine.
@OUTPUT 4
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, if INFO = 0, the eigenvalues in ascending order.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, the contents of E are destroyed.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
        eigenvectors of the matrix A, with the i-th column of Z
        holding the eigenvector associated with D(i).
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of E did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG mI1,mI2
@ARG I1,O0
@ARG I2,O1
@ARG O2
@ARG lO2
@ARG ?
@ARG O3
@CODE
extern void dstev(char *jobz, int *n, double *d, double *e, double *z,
                  int *ldz, double *work, int *info);

int ldz, lwork;
double *work;

if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else
   return NS_PROT_BAD_VALUES;

if (*@I0@ == 'V') {
   ldz = (*@mI1@ > 1) ? *@mI1@ : 1;
} else ldz = 1;

lwork = ((2 * *@mI1@ - 2) > 1 ) ? (2 * *@mI1@ - 2) : 1;

if (*@I0@ == 'V') {
   work = (double *) malloc(sizeof(double) * lwork);
   @O2@ = (double *) malloc(sizeof(double) * *@mI1@ * ldz);
} else {
   work = (double *) malloc(sizeof(double));
   @O2@ = (double *) malloc(sizeof(double));
}

@O3@ = (int *) malloc(sizeof(int));

dstev(@I0@, @mI1@, @I1@, @I2@, @O2@, &ldz, work, @O3@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;

@O1@ = @I2@;
*@mO1@ = *@mI2@;

*@mO2@ = ldz;
*@nO2@ = *@mI1@;

@END_CODE


#
# DSBEVD
#
@PROBLEM dsbevd
@FUNCTION dsbevd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/DivideandConquer/Eig_and_Singular/
@DESCRIPTION
DSBEVD computes all the eigenvalues and, optionally, eigenvectors of
a real symmetric band matrix A. If eigenvectors are desired, it uses
a divide and conquer algorithm.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT SCALAR I kd
KD      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).
@OUTPUT 4
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On exit, AB is overwritten by values generated during the
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
        eigenvectors of the matrix A, with the i-th column of Z
        holding the eigenvector associated with W(i).
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of an intermediate tridiagonal
              form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
#JOBZ
@ARG I0
# UPLO
@ARG I1
# N
@ARG nI3
#KD
@ARG I2
#AB
@ARG I3,O0
#LDAB
@ARG lI3,lO0
# W
@ARG O1
# Z
@ARG O2
# LDZ
@ARG lO2
#WORK
@ARG ?
@ARG ?
@ARG ?
@ARG ?
#INFO
@ARG O3
@COMP mI3=op(+,array(I2,0),1)
@CODE
extern void dsbevd(char *jobz, char *uplo, int *n, int *kd,
                   double *ab, int *ldab, double *w, double *z,
                   int *ldz, double *work, int *lwork, int *iwork,
                   int *liwork, int *info);

int ldab, ldz, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldab = *@I2@ + 1;
if (*@I0@ == 'V') {
   ldz = (*@nI3@ > 1) ? *@nI3@ : 1;
} else ldz = 1;

@O1@ = (double *) malloc(sizeof(double) * *@nI3@);
@O2@ = (double *) malloc(sizeof(double) * *@nI3@ * ldz);

if (*@I0@ == 'N') {
   lwork =  (2 * *@nI3@ > 1) ? 2 * *@nI3@ : 1;
} else {
   lwork = 1 + 5 * *@nI3@ + 2 * *@nI3@ * *@nI3@;
}

work = (double *) malloc(sizeof(double) * lwork);
liwork = 3 + 5 * *@nI3@;
iwork = (int *) malloc(sizeof(int) * liwork);
@O3@ = (int *) malloc(sizeof(int));

dsbevd(@I0@, @I1@, @nI3@, @I2@, @I3@, &ldab, @O1@,
       @O2@, &ldz, work, &lwork, iwork, &liwork, @O3@);

@O0@ = @I3@;
*@mO0@ = *@mI3@;
*@nO0@ = *@nI3@;

*@mO1@ = *@nI3@;

*@mO2@ = ldz;
*@nO2@ = *@nI3@;
@END_CODE

#
# DSBEVX
#
@PROBLEM dsbevx
@FUNCTION dsbevx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Expert/Eig_and_Singular/
@DESCRIPTION
DSBEVX computes selected eigenvalues and, optionally, eigenvectors
of a real symmetric band matrix A.  Eigenvalues and eigenvectors can
be selected by specifying either a range of values or a range of
indices for the desired eigenvalues.
http://www.netlib.org/lapack/
@INPUT 10
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT SCALAR I kd
KD      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).

        On exit, AB is overwritten by values generated during the
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        Eigenvalues will be computed most accurately when ABSTOL is
        set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        If this routine returns with INFO>0, indicating that some
        eigenvectors did not converge, try setting ABSTOL to
        2*DLAMCH('S').

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.
@OUTPUT 7
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).

        On exit, AB is overwritten by values generated during the
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT MATRIX D q
Q       (output) DOUBLE PRECISION array, dimension (LDQ, N)
        If JOBZ = 'V', the N-by-N orthogonal matrix used in the
                       reduction to tridiagonal form.
        If JOBZ = 'N', the array Q is not referenced.
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        If an eigenvector fails to converge, then that column of Z
        contains the latest approximation to the eigenvector, and the
        index of the eigenvector is returned in IFAIL.
        If JOBZ = 'N', then Z is not referenced.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I ifail
IFAIL   (output) INTEGER array, dimension (N)
        If JOBZ = 'V', then if INFO = 0, the first M elements of
        IFAIL are zero.  If INFO > 0, then IFAIL contains the
        indices of the eigenvectors that failed to converge.
        If JOBZ = 'N', then IFAIL is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, then i eigenvectors failed to converge.
              Their indices are stored in array IFAIL.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI4
@ARG I3
@ARG I4,O0
@ARG lI4,lO0
@ARG O1
@ARG lO1
@ARG I5
@ARG I6
@ARG I7
@ARG I8
@ARG I9
@ARG O2
@ARG O3
@ARG O4
@ARG lO4
@ARG ?
@ARG ?
@ARG O5
@ARG O6
@COMP mI4=op(+,array(I3,0),1)
@CODE
extern void dsbevx(char *jobz, char *range, char *uplo, int *n,
                   int *kd, double *ab, int *ldab, double *q,
                   int *ldq, double *vl, double *vu, int *il, int *iu,
                   double *abstol, int *m, double *w, double *z,
                   int *ldz, double *work, int *iwork, int *ifail,
                   int *info);

int ldab, ldq, ldz, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldab = (*@I3@ > 1) ? *@I3@ : 1;
ldab +=1;
ldq = (*@nI4@ > 1) ? *@nI4@ : 1;
ldz = (*@nI4@ > 1) ? *@nI4@ : 1;

liwork = (5 * *@nI4@ > 1) ? 5 * *@nI4@ : 1;
lwork = (7 * *@nI4@ > 1) ? 7 * *@nI4@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O1@ = (double *) malloc(sizeof(double) * ldq * *@nI4@);
@O2@ = (int *) malloc(sizeof(int));
@O3@ = (double *) malloc(sizeof(double) * *@nI4@);
@O4@ = (double *) malloc(sizeof(double) * ldz * *@nI4@);
@O5@ = (int *) malloc(sizeof(int) * *@nI4@);
@O6@ = (int *) malloc(sizeof(int));

dsbevx(@I0@, @I1@, @I2@, @nI4@, @I3@, @I4@, &ldab, @O1@, &ldq,
       @I5@, @I6@, @I7@, @I8@, @I9@, @O2@, @O3@, @O4@, &ldz,
       work, iwork, @O5@, @O6@);

@O0@ = @I4@;
*@mO0@ = *@mI4@;
*@nO0@ = *@nI4@;

*@mO1@ = *@nI4@;
*@nO1@ = *@nI4@;

*@mO3@ = *@nI4@;

*@mO4@ = *@nI4@;
*@nO4@ = *@nI4@;

*@mO5@ = *@nI4@;
@END_CODE

#
# DSBEV
#
@PROBLEM dsbev
@FUNCTION dsbev
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Eig_and_Singular/
@DESCRIPTION
DSBEV computes all the eigenvalues and, optionally, eigenvectors of
a real symmetric band matrix A.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT SCALAR I kd
KD      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).
@OUTPUT 4
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
        eigenvectors of the matrix A, with the i-th column of Z
        holding the eigenvector associated with W(i).
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of an intermediate tridiagonal
              form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI3
@ARG I2
@ARG I3,O0
@ARG lI3,lO0
@ARG O1
@ARG O2
@ARG lO2
@ARG ?
@ARG O3
@COMP mI3=op(+,array(I2,0),1)
@CODE
extern void dsbev(char *jobz, char *uplo, int *n, int *kd,
                  double *ab, int *ldab, double *w, double *z,
                  int *ldz, double *work, int *info);

int ldab, lwork;
int ldz;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

if (*@I0@ == 'V') {
   ldz = (*@nI3@ > 1) ? *@nI3@ : 1;
} else ldz = 1;

ldab = *@I2@ + 1;
@O1@ = (double *) malloc(sizeof(double) * *@nI3@);
@O2@ = (double *) malloc(sizeof(double) * *@nI3@ * ldz);
@O3@ = (int *) malloc(sizeof(int));
lwork = (3 * *@nI3@ - 2 > 1) ? 3 * *@nI3@ - 2 : 1;
work = (double *) malloc(sizeof(double) * lwork);

dsbev(@I0@, @I1@, @nI3@, @I2@, @I3@, &ldab, @O1@, @O2@, &ldz, work, @O3@);

@O0@ = @I3@;
*@mO0@ = *@mI3@;
*@nO0@ = *@nI3@;

*@mO1@ = *@nI3@;

*@mO2@ = ldz;
*@nO2@ = *@nI3@;
@END_CODE


#
# DSYEVD
#
@PROBLEM dsyevd
@FUNCTION dsyevd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/DivideandConquer/Eig_and_Singular/
@DESCRIPTION
DSYEVD computes all eigenvalues and, optionally, eigenvectors of a
real symmetric matrix A. If eigenvectors are desired, it uses a
divide and conquer algorithm.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
@OUTPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, if JOBZ = 'V', then if INFO = 0, A contains the
        orthonormal eigenvectors of the matrix A.
        If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
        or the upper triangle (if UPLO='U') of A, including the
        diagonal, is destroyed.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of an intermediate tridiagonal
              form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI2,mI2
@ARG I2,O0
@ARG lI2,lO0
@ARG O1
@ARG ?
@ARG ?
@ARG ?
@ARG ?
@ARG O2
@CODE
extern void dsyevd(char *jobz, char *uplo, int *n, double *a, int *lda,
                   double *w, double *work, int *lwork, int *iwork,
                   int *liwork, int *info);

int lda, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

if (*@mI2@ != *@nI2@) return NS_PROT_DIM_MISMATCH;

lda = (*@nI2@ > 1) ? *@nI2@ : 1;

if (*@I0@ == 'N') {
   liwork = 1;
   lwork = 1 + 2 * *@nI2@;
} else {
   liwork = 3 + 5 * *@nI2@;
   lwork = 1 + 6 * *@nI2@ + 2 * *@nI2@ * *@nI2@;
}

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O1@ = (double *) malloc(sizeof(double) * *@nI2@);
@O2@ = (int *) malloc(sizeof(int));

dsyevd(@I0@, @I1@, @nI2@, @I2@, &lda, @O1@, work, &lwork, 
       iwork, &liwork, @O2@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

*@mO1@ = *@nI2@;
@END_CODE

#
# DSYEVX
#
@PROBLEM dsyevx
@FUNCTION dsyevx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Expert/Eig_and_Singular/
@DESCRIPTION
DSYEVX computes selected eigenvalues and, optionally, eigenvectors
of a real symmetric matrix A.  Eigenvalues and eigenvectors can be
selected by specifying either a range of values or a range of indices
for the desired eigenvalues.
http://www.netlib.org/lapack/
@INPUT 9
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
        On exit, the lower triangle (if UPLO='L') or the upper
        triangle (if UPLO='U') of A, including the diagonal, is
        destroyed.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        Eigenvalues will be computed most accurately when ABSTOL is
        set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        If this routine returns with INFO>0, indicating that some
        eigenvectors did not converge, try setting ABSTOL to
        2*DLAMCH('S').

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.
@OUTPUT 5
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        If an eigenvector fails to converge, then that column of Z
        contains the latest approximation to the eigenvector, and the
        index of the eigenvector is returned in IFAIL.
        If JOBZ = 'N', then Z is not referenced.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I ifail
IFAIL   (output) INTEGER array, dimension (N)
        If JOBZ = 'V', then if INFO = 0, the first M elements of
        IFAIL are zero.  If INFO > 0, then IFAIL contains the
        indices of the eigenvectors that failed to converge.
        If JOBZ = 'N', then IFAIL is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, then i eigenvectors failed to converge.
              Their indices are stored in array IFAIL.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI3,mI3
@ARG I3
@ARG lI3
@ARG I4
@ARG I5
@ARG I6
@ARG I7
@ARG I8
@ARG O0
@ARG O1
@ARG O2
@ARG lO2
@ARG ?
@ARG ?
@ARG ?
@ARG O3
@ARG O4
@CODE
extern void dsyevx(char *jobz, char *range, char *uplo, int *n,
                   double *a, int *lda, double *vl, double *vu,
                   int *il, int *iu, double *abstol, int *m, double *w,
                   double *z, int *ldz, double *work, int *lwork,
                   int *iwork, int *ifail, int *info);

int lda, ldz, liwork, lwork, *iwork;
int nb=64;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

if (*@mI3@ != *@nI3@) return NS_PROT_DIM_MISMATCH;

lda = (*@nI3@ > 1) ? *@nI3@ : 1;
ldz = (*@nI3@ > 1) ? *@nI3@ : 1;

liwork = (5 * *@nI3@ > 1) ? 5 * *@nI3@ : 1;
lwork = ((nb+3) * *@nI3@ > 1) ? (nb+3) * *@nI3@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O0@ = (int *) malloc(sizeof(int));
@O1@ = (double *) malloc(sizeof(double) * *@nI3@);
@O2@ = (double *) malloc(sizeof(double) * ldz * *@nI3@);
@O3@ = (int *) malloc(sizeof(int) * *@nI3@);
@O4@ = (int *) malloc(sizeof(int));

dsyevx(@I0@, @I1@, @I2@, @nI3@, @I3@, &lda, @I4@, @I5@,
       @I6@, @I7@, @I8@, @O0@, @O1@, @O2@, &ldz, work, &lwork, 
       iwork, @O3@, @O4@);

*@mO1@ = *@nI3@;

*@mO2@ = *@mI3@;
*@nO2@ = *@nI3@;

*@mO3@ = *@nI3@;
@END_CODE

#
# DSYEVR
#
@PROBLEM dsyevr
@FUNCTION dsyevr
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/RRR/Eig_and_Singular/
@DESCRIPTION
DSYEVR computes selected eigenvalues and, optionally, eigenvectors
of a real symmetric matrix T.  Eigenvalues and eigenvectors can be
selected by specifying either a range of values or a range of
indices for the desired eigenvalues.

Whenever possible, DSYEVR calls DSTEGR to compute the
eigenspectrum using Relatively Robust Representations.  DSTEGR
computes eigenvalues by the dqds algorithm, while orthogonal
eigenvectors are computed from various "good" L D L^T representations
(also known as Relatively Robust Representations). Gram-Schmidt
orthogonalization is avoided as far as possible. More specifically,
the various steps of the algorithm are as follows. For the i-th
unreduced block of T,
   (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T
        is a relatively robust representation,
   (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high
       relative accuracy by the dqds algorithm,
   (c) If there is a cluster of close eigenvalues, "choose" sigma_i
       close to the cluster, and go to step (a),
   (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T,
       compute the corresponding eigenvector by forming a
       rank-revealing twisted factorization.
The desired accuracy of the output can be specified by the input
parameter ABSTOL.

For more details, see "A new O(n^2) algorithm for the symmetric
tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon,
Computer Science Division Technical Report No. UCB//CSD-97-971,
UC Berkeley, May 1997.

Note 1 : DSYEVR calls DSTEGR when the full spectrum is requested
on machines which conform to the ieee-754 floating point standard.
DSYEVR calls DSTEBZ and SSTEIN on non-ieee machines and
when partial spectrum requests are made.

Normal execution of DSTEGR may create NaNs and infinities and
hence may abort due to a floating point exception in environments
which do not handle NaNs and infinities in the ieee standard default
manner.
http://www.netlib.org/lapack/
@INPUT 9
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and
********** DSTEIN are called
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
        On exit, the lower triangle (if UPLO='L') or the upper
        triangle (if UPLO='U') of A, including the diagonal, is
        destroyed.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.

        If high relative accuracy is important, set ABSTOL to
        DLAMCH( 'Safe minimum' ).  Doing so will guarantee that
        eigenvalues are computed to high relative accuracy when
        possible in future releases.  The current code does not
        make any guarantees about high relative accuracy, but
        furutre releases will. See J. Barlow and J. Demmel,
        "Computing Accurate Eigensystems of Scaled Diagonally
        Dominant Matrices", LAPACK Working Note #7, for a discussion
        of which matrices define their eigenvalues to high relative
        accuracy.
@OUTPUT 5
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        If JOBZ = 'N', then Z is not referenced.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I isuppz
ISUPPZ  (output) INTEGER array, dimension ( 2*max(1,M) )
        The support of the eigenvectors in Z, i.e., the indices
        indicating the nonzero elements in Z. The i-th eigenvector
        is nonzero only in elements ISUPPZ( 2*i-1 ) through
        ISUPPZ( 2*i ).
******* Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  Internal error
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI3,mI3
@ARG I3
@ARG lI3
@ARG I4
@ARG I5
@ARG I6
@ARG I7
@ARG I8
@ARG O0
@ARG O1
@ARG O2
@ARG lO2
@ARG O3
@ARG ?
@ARG ?
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dsyevr(char *jobz, char *range, char *uplo, int *n,
                   double *a, int *lda, double *vl, double *vu,
                   int *il, int *iu, double *abstol, int *m, double *w,
                   double *z, int *ldz, int *isuppz, double *work,
                   int *lwork, int *iwork, int *liwork, int *info);

int lda, ldz, liwork, lwork, *iwork;
int nb=64;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

if (*@mI3@ != *@nI3@) return NS_PROT_DIM_MISMATCH;

lda = (*@nI3@ > 1) ? *@nI3@ : 1;
ldz = (*@nI3@ > 1) ? *@nI3@ : 1;

liwork = (10 * *@nI3@ > 1) ? 10 * *@nI3@ : 1;
lwork = ((nb+6) * *@nI3@ > 1) ? (nb+6) * *@nI3@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O0@ = (int *) malloc(sizeof(int));
@O1@ = (double *) malloc(sizeof(double) * *@nI3@);
@O2@ = (double *) malloc(sizeof(double) * ldz * *@nI3@);
@O3@ = (int *) malloc(sizeof(int) * 2 * *@nI3@);
@O4@ = (int *) malloc(sizeof(int));

dsyevr(@I0@, @I1@, @I2@, @nI3@, @I3@, &lda, @I4@, @I5@,
       @I6@, @I7@, @I8@, @O0@, @O1@, @O2@, &ldz, @O3@, work, &lwork, 
       iwork, &liwork, @O4@);

*@mO1@ = *@nI3@;

*@mO2@ = *@mI3@;
*@nO2@ = *@nI3@;

*@mO3@ = 2 * *@nI3@;
@END_CODE


#
# DSYEV
#
@PROBLEM dsyev
@FUNCTION dsyev
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Eig_and_Singular/
@DESCRIPTION
DSYEV computes all eigenvalues and, optionally, eigenvectors of a
real symmetric matrix A.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
@OUTPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, if JOBZ = 'V', then if INFO = 0, A contains the
        orthonormal eigenvectors of the matrix A.
        If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
        or the upper triangle (if UPLO='U') of A, including the
        diagonal, is destroyed.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the algorithm failed to converge; i
              off-diagonal elements of an intermediate tridiagonal
              form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI2,mI2
@ARG I2,O0
@ARG lI2,lO0
@ARG O1
@ARG ?
@ARG ?
@ARG O2
@CODE
extern void dsyev(char *jobz, char *uplo, int *n, double *a,
                  int *lda, double *w, double *work, int *lwork,
                  int *info);

int lda, lwork, nb;
/*
int one = 1;
int minusone = -1;
*/
double *work;

/*
extern int ilaenv();
*/

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

if (*@mI2@ != *@nI2@) return NS_PROT_DIM_MISMATCH;

/*
nb = ilaenv( &one, "dsytrd", *@I1@, *@nI2@, &minusone, &minusone, &minusone );
*/
nb = 64;
lwork = ((nb+2) * *@nI2@ > 1) ? (nb+2) * *@nI2@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
@O2@ = (int *) malloc(sizeof(int));
@O1@ = (double *) malloc(sizeof(double) * *@nI2@);

lda = (*@nI2@ > 1) ? *@nI2@ : 1;

dsyev(@I0@, @I1@, @nI2@, @I2@, &lda, @O1@, work, &lwork, @O2@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

*@mO1@ = *@nI2@;

@END_CODE
#
# Double type LAPACK routines:  Simple Drivers:  For Linear Equations
# 
# Functions defined here:
#
# DGESV
# DGBSV
# DGTSV
# DPOSV
# DPBSV
# DPTSV
# DSYSV


#
# DSYSV
#
@PROBLEM dsysv
@FUNCTION dsysv
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
DSYSV computes the solution to a real system of linear equations
   A * X = B,
where A is an N-by-N symmetric matrix and X and B are N-by-NRHS
matrices.

The diagonal pivoting method is used to factor A as
   A = U * D * U**T,  if UPLO = 'U', or
   A = L * D * L**T,  if UPLO = 'L',
where U (or L) is a product of permutation and unit upper (lower)
triangular matrices, and D is symmetric and block diagonal with
1-by-1 and 2-by-2 diagonal blocks.  The factored form of A is then
used to solve the system of equations A * X = B.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the leading
        N-by-N upper triangular part of A contains the upper
        triangular part of the matrix A, and the strictly lower
        triangular part of A is not referenced.  If UPLO = 'L', the
        leading N-by-N lower triangular part of A contains the lower
        triangular part of the matrix A, and the strictly upper
        triangular part of A is not referenced.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the N-by-NRHS right hand side matrix B.
@OUTPUT 4
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, if INFO = 0, the block diagonal matrix D and the
        multipliers used to obtain the factor U or L from the
        factorization A = U*D*U**T or A = L*D*L**T as computed by
        DSYTRF.
@OBJECT VECTOR I ipiv
IPIV    (output) INTEGER array, dimension (N)
        Details of the interchanges and the block structure of D, as
        determined by DSYTRF.  If IPIV(k) > 0, then rows and columns
        k and IPIV(k) were interchanged, and D(k,k) is a 1-by-1
        diagonal block.  If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0,
        then rows and columns k-1 and -IPIV(k) were interchanged and
        D(k-1:k,k-1:k) is a 2-by-2 diagonal block.  If UPLO = 'L' and
        IPIV(k) = IPIV(k+1) < 0, then rows and columns k+1 and
        -IPIV(k) were interchanged and D(k:k+1,k:k+1) is a 2-by-2
        diagonal block.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0: successful exit
        < 0: if INFO = -i, the i-th argument had an illegal value
        > 0: if INFO = i, D(i,i) is exactly zero.  The factorization
             has been completed, but the block diagonal matrix D is
             exactly singular, so the solution could not be computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
#UPLO, char
@ARG I0
#N, int
@ARG mI1,nI1,mI2
#NRHS, int
@ARG nI2
#A, matrix (LDA, N), but actually (N, N)
@ARG I1,O0
#LDA, int
@ARG lI1
#IPIV, array of int, (N)
@ARG O1
#B, matrix, (LDB, NRHS), but actually (N, NRHS)
@ARG I2,O2
#LDB, int
@ARG lI2
# LWORK, WORK
@ARG ?
@ARG ?
#INFO, int
@ARG O3

@CODE
extern void dsysv(char *uplo, int *n, int *nrhs, double *a, int *lda,
                  int *ipiv, double *b, int *ldb, double *work,
                  int *lwork, int *info);

int lwork, nb;
int lda, ldb;
/*
int one = 1;
int minusone = -1;
*/
double *work;

/*
extern int ilaenv();
*/

if (*@mI1@ != *@nI1@ || *@nI1@ != *@mI2@) return NS_PROT_DIM_MISMATCH;

if (*@I0@ == 'u' || *@I0@ == 'U') 
   *@I0@ = 'U';
else if (*@I0@ == 'l' || *@I0@ == 'L') 
   *@I0@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

@O1@ = (int *) malloc(sizeof(int) * *@nI1@);
@O3@ = (int *) malloc(sizeof(int));

/*
nb = ilaenv(&one, "dsytrf", @I0@, @nI1@, &minusone, &minusone,&minusone);
*/
nb = 64;
lwork = *@nI1@ * nb;
lwork = (lwork > 1) ? lwork : 1;
work = (double *) malloc(sizeof(double) * lwork);

lda = (*@nI1@ > 1) ? *@nI1@ : 1;
ldb = (*@mI2@ > 1) ? *@mI2@ : 1;
dsysv(@I0@, @nI1@, @nI2@, @I1@, &lda, @O1@, @I2@, &ldb, work, &lwork, @O3@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

*@mO1@ = *@mI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;
*@nO2@ = *@nI2@;

@END_CODE

#
# DPTSV
#
@PROBLEM dptsv
@FUNCTION dptsv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
DPTSV computes the solution to a real system of linear equations
A*X = B, where A is an N-by-N symmetric positive definite tridiagonal
matrix, and X and B are N-by-NRHS matrices.

A is factored as A = L*D*L**T, and the factored form of A is then
used to solve the system of equations.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, the n diagonal elements of the tridiagonal matrix
        A. 
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N-1)
        On entry, the (n-1) subdiagonal elements of the tridiagonal
        matrix A. 
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
        On entry, the N-by-NRHS right hand side matrix B.
@OUTPUT 4
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, the n diagonal elements of the diagonal matrix
        D from the factorization A = L*D*L**T.
@OBJECT VECTOR D e
E       (input/output) DOUBLE PRECISION array, dimension (N-1)
        On exit, the (n-1) subdiagonal elements of the unit 
        bidiagonal factor L from the L*D*L**T factorization of A.  
        (E can also be regarded as the superdiagonal of the unit
        bidiagonal factor U from the U**T*D*U factorization of A.)
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
        On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the leading minor of order i is not
              positive definite, and the solution has not been
              computed.  The factorization has not been completed
              unless i = N.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# N
@ARG mI0,mI2

# NRHS
@ARG nI2

# D (N)
@ARG I0,O0

# E (N-1)
@ARG I1,O1

# B, (LDB,N)
@ARG I2,O2

# LDB, >= max(1,N)
@ARG lI2

# INFO
@ARG O3

@COMP mI1=op(-,mI0,1)
@CODE
extern void dptsv(int *n, int *nrhs, double *d, double *e, double *b,
                  int *ldb, int *info);

int ldb;

if (*@mI0@ != *@mI2@) return NS_PROT_DIM_MISMATCH;

ldb = (*@mI2@ > 1) ? *@mI2@ : 1;
@O3@ = (int *) malloc(sizeof(int));

dptsv(@mI0@, @nI2@, @I0@, @I1@, @I2@, &ldb, @O3@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;

@O1@ = @I1@;
*@mO1@ = *@mI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;
*@nO2@ = *@nI2@;
@END_CODE
#
# DPBSV
#
@PROBLEM dpbsv
@FUNCTION dpbsv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
DPBSV computes the solution to a real system of linear equations
   A * X = B,
where A is an N-by-N symmetric positive definite band matrix and X
and B are N-by-NRHS matrices.

The Cholesky decomposition is used to factor A as
   A = U**T * U,  if UPLO = 'U', or
   A = L * L**T,  if UPLO = 'L',
where U is an upper triangular band matrix, and L is a lower
triangular band matrix, with the same number of superdiagonals or
subdiagonals as A.  The factored form of A is then used to solve the
system of equations A * X = B.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT SCALAR I kd
KD      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KD >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB,N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(KD+1+i-j,j) = A(i,j) for max(1,j-KD)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(N,j+KD).
        See below for further details.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the N-by-NRHS right hand side matrix B.
@OUTPUT 3
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB,N)
        On exit, if INFO = 0, the triangular factor U or L from the
        Cholesky factorization A = U**T*U or A = L*L**T of the band
        matrix A, in the same storage format as A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the leading minor of order i of A is not
              positive definite, so the factorization could not be
              completed, and the solution has not been computed.
===============
Further Details
===============

The band storage scheme is illustrated by the following example, when
N = 6, KD = 2, and UPLO = 'U':

On entry:                       On exit:
    *    *   a13  a24  a35  a46      *    *   u13  u24  u35  u46
    *   a12  a23  a34  a45  a56      *   u12  u23  u34  u45  u56
   a11  a22  a33  a44  a55  a66     u11  u22  u33  u44  u55  u66

Similarly, if UPLO = 'L' the format of A is as follows:
On entry:                       On exit:
   a11  a22  a33  a44  a55  a66     l11  l22  l33  l44  l55  l66
   a21  a32  a43  a54  a65   *      l21  l32  l43  l54  l65   *
   a31  a42  a53  a64   *    *      l31  l42  l53  l64   *    *

Array elements marked * are not used by the routine.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# uplo, char
@ARG I0
# n, num. linear equations, int, order of A
@ARG nI2
# kd, int, number of super/subdiagonals of matrix A
@ARG I1
# nrhs, num of columns of matrix B
@ARG nI3
# AB, double matrix (LDAB, N)
@ARG I2,O0
# LDAB, leading dimension of matrix AB.  LDAB >= KD + 1
@ARG lI2
# B, double matrix (LDB, NRHS)
@ARG I3,O1
# ldb, leading dimension of matrix B, ldb>=max(1,N)
@ARG lI3,mI3
# info, char
@ARG O2
@COMP mI2=op(+,array(I1,0),1)
@CODE
extern void dpbsv(char *uplo, int *n, int *kd, int *nrhs, double *ab,
                  int *ldab, double *b, int *ldb, int *info);

int ldb;

if (*@I0@ == 'u' || *@I0@ == 'U') 
   *@I0@ = 'U';
else if (*@I0@ == 'l' || *@I0@ == 'L') 
   *@I0@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldb = (*@mI3@ > 1) ? *@mI3@ : 1;

@O2@ = (int *) malloc(sizeof(int));

dpbsv(@I0@, @nI2@, @I1@, @nI3@, @I2@, @mI2@, @I3@, &ldb, @O2@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

@O1@ = @I3@;
*@mO1@ = *@mI3@;
*@nO1@ = *@nI3@;

@END_CODE
#
# DPOSV
#
@PROBLEM dposv
@FUNCTION dposv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
DPOSV computes the solution to a real system of linear equations
   A * X = B,
where A is an N-by-N symmetric positive definite matrix and X and B
are N-by-NRHS matrices.

The Cholesky decomposition is used to factor A as
   A = U**T* U,  if UPLO = 'U', or
   A = L * L**T,  if UPLO = 'L',
where U is an upper triangular matrix and L is a lower triangular
matrix.  The factored form of A is then used to solve the system of
equations A * X = B.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the leading
        N-by-N upper triangular part of A contains the upper
        triangular part of the matrix A, and the strictly lower
        triangular part of A is not referenced.  If UPLO = 'L', the
        leading N-by-N lower triangular part of A contains the lower
        triangular part of the matrix A, and the strictly upper
        triangular part of A is not referenced.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the N-by-NRHS right hand side matrix B.
@OUTPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, if INFO = 0, the factor U or L from the Cholesky
        factorization A = U**T*U or A = L*L**T.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, the leading minor of order i of A is not
              positive definite, so the factorization could not be
              completed, and the solution has not been computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG nI1,mI1,mI2
@ARG nI2
@ARG I1,O0
@ARG lI1
@ARG I2,O1
@ARG lI2
@ARG O2
@CODE
extern void dposv(char *uplo, int *n, int *nrhs, double *a, int *lda,
                  double *b, int *ldb, int *info);

int lda, ldb;

if (*@I0@ == 'u' || *@I0@ == 'U') 
   *@I0@ = 'U';
else if (*@I0@ == 'l' || *@I0@ == 'L') 
   *@I0@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

#if ((*@I0@ != 'L')&&(*@I0@ != 'U'))
#  return NS_PROT_BAD_VALUES;

if (*@mI1@ != *@nI1@ || *@nI1@ != *@mI2@) return NS_PROT_DIM_MISMATCH;

@O2@ = (int *) malloc(sizeof(int));

lda = (*@mI1@ > 1) ? *@mI1@ : 1;
ldb = (*@mI2@ > 1) ? *@mI2@ : 1;

dposv(@I0@, @nI1@, @nI2@, @I1@, &lda, @I2@, &ldb, @O2@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

@O1@ = @I2@;
*@mO1@ = *@mI2@;
*@nO1@ = *@nI2@;

@END_CODE

#
# Problem:  DGBSV
#
@PROBLEM dgbsv
@FUNCTION dgbsv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
   DGBSV computes the solution to a real system of linear equations
   A * X = B, where A is a band matrix of order N with KL subdiagonals
   and KU superdiagonals, and X and B are N-by-NRHS matrices.
 
   The LU decomposition with partial pivoting and row interchanges is
   used to factor A as A = L * U, where L is a product of permutation
   and unit lower triangular matrices with KL subdiagonals, and U is
   upper triangular with KL+KU superdiagonals.  The factored form of A
   is then used to solve the system of equations A * X = B.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR I kl
KL      (input) INTEGER
   The number of subdiagonals within the band of A.  KL >= 0.
@OBJECT SCALAR I ku
KU      (input) INTEGER
   The number of superdiagonals within the band of A.  KU >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB,N)
   On entry, the matrix A in band storage, in rows KL+1 to
   2*KL+KU+1; rows 1 to KL of the array need not be set.
   The j-th column of A is stored in the j-th column of the
   array AB as follows:
   AB(KL+KU+1+i-j,j) = A(i,j) for max(1,j-KU)<=i<=min(N,j+KL)
   On exit, details of the factorization: U is stored as an
   upper triangular band matrix with KL+KU superdiagonals in
   rows 1 to KL+KU+1, and the multipliers used during the
   factorization are stored in rows KL+KU+2 to 2*KL+KU+1.
   See below for further details.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
   On entry, the N-by-NRHS right hand side matrix B.
   On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OUTPUT 4
@OBJECT MATRIX D ab
 On exit, details of the factorization: U is stored as an
upper triangular band matrix with KL+KU superdiagonals in
rows 1 to KL+KU+1, and the multipliers used during the
factorization are stored in rows KL+KU+2 to 2*KL+KU+1.

@OBJECT VECTOR I ipiv
IPIV    (output) INTEGER array, dimension (N)
   The pivot indices that define the permutation matrix P;
   row i of the matrix was interchanged with row IPIV(i).
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
   On entry, the N-by-NRHS right hand side matrix B.
   On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
   = 0:  successful exit
   < 0:  if INFO = -i, the i-th argument had an illegal value
   > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
         has been completed, but the factor U is exactly
         singular, and the solution has not been computed.

*  Further Details
*  ===============
*  The band storage scheme is illustrated by the following example, when
*  M = N = 6, KL = 2, KU = 1:
*
*  On entry:                       On exit:
*
*      *    *    *    +    +    +       *    *    *   u14  u25  u36
*      *    *    +    +    +    +       *    *   u13  u24  u35  u46
*      *   a12  a23  a34  a45  a56      *   u12  u23  u34  u45  u56
*     a11  a22  a33  a44  a55  a66     u11  u22  u33  u44  u55  u66
*     a21  a32  a43  a54  a65   *      m21  m32  m43  m54  m65   *
*     a31  a42  a53  a64   *    *      m31  m42  m53  m64   *    *
*
*  Array elements marked * are not used by the routine; elements marked
*  + need not be set on entry, but are required by the routine to store
*  elements of U because of fill-in resulting from the row interchanges.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
#
# n, order of matrix A
@ARG nI2,mI3
# kl, scalar integer
@ARG I0
# ku, scalar integer
@ARG I1
# nrhs, 
@ARG nI3
# AB, matrix of doubles
@ARG I2,O0
# ldab, leading dimension of AB
@ARG lI2
# ipiv, vector of ints, output
@ARG O1
# B, matrix of doubles
@ARG I3,O2
# ldb, leading dimension of B
@ARG lI3
# info, scalar integer
@ARG O3
@COMP mI2=op(+,op(+,array(I1,0),1),op(*,array(I0,0),2))
#
# Code segment
#
@CODE
extern void dgbsv(int *n, int *kl, int *ku, int *nrhs, double *ab,
                  int *ldab, int *ipiv, double *b, int *ldb, int *info);

int ldb,ldab;

#if (*@mI3@ != *@nI2@) return NS_PROT_DIM_MISMATCH;

@O1@ = (int *) malloc(sizeof(int) * (*@nI2@));
*@mO1@ = *@nI2@;

@O3@ = (int *) malloc(sizeof(int));

ldb = (*@mI3@ > 1) ? *@mI3@ : 1;
ldab = (*@mI2@ > 1) ? *@mI2@ : 1;

dgbsv(@nI2@, @I0@, @I1@, @nI3@, @I2@, &ldab, @O1@, @I3@, &ldb, @O3@);

@O0@ = @I2@;
*@nO0@ = *@nI2@;
*@mO0@ = *@mI2@;
@O2@ = @I3@;
*@mO2@ = *@mI3@;
*@nO2@ = *@nI3@;

@END_CODE
#
# DGTSV
#
@PROBLEM dgtsv
@FUNCTION dgtsv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
   DGTSV  solves the equation
 
      A*X = B,
 
   where A is an N-by-N tridiagonal matrix, by Gaussian elimination with
   partial pivoting.
 
   Note that the equation  A'*X = B  may be solved by interchanging the
   order of the arguments DU and DL.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT VECTOR D dl
DL      (input/output) DOUBLE PRECISION array, dimension (N-1)
        On entry, DL must contain the (n-1) subdiagonal elements of
        A.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, D must contain the diagonal elements of A.
@OBJECT VECTOR D du
DU      (input/output) DOUBLE PRECISION array, dimension (N-1)
        On entry, DU must contain the (n-1) superdiagonal elements
        of A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the N-by-NRHS right hand side matrix B.
@OUTPUT 5
@OBJECT VECTOR D dl
DL      (input/output) DOUBLE PRECISION array, dimension (N-1)
        On exit, DL is overwritten by the (n-2) elements of the
        second superdiagonal of the upper triangular matrix U from
        the LU factorization of A, in DL(1), ..., DL(n-2).
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, D is overwritten by the n diagonal elements of U.
@OBJECT VECTOR D du
DU      (input/output) DOUBLE PRECISION array, dimension (N-1)
        On exit, DU is overwritten by the (n-1) elements of the first
        superdiagonal of U.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, if INFO = 0, the N-by-NRHS solution matrix X.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, U(i,i) is exactly zero, and the solution
              has not been computed.  The factorization has not been
              completed unless i = N.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# n order of matrix A/vector D.
@ARG mI1, mI3
# nrhs, number cols. of B
@ARG nI3
# dl, array, i/o
@ARG I0,O0
# d, double precision vector, i/o
@ARG I1,O1
# du, double precision vector, i/o
@ARG I2,O2
# b, double precision matrix, i/o
@ARG I3,O3
# ldb, leading dimension of B
@ARG lI3
# info, scalar integer
@ARG O4
@COMP mI0=op(-,mI1,1)
@COMP mI2=op(-,mI1,1)
@CODE
extern void dgtsv(int *n, int *nrhs, double *dl, double *d, double *du,
                  double *b, int *ldb, int *info);

int ldb;

@O4@ = (int *) malloc(sizeof(int));


ldb = (*@mI1@ > 1) ? *@mI1@ : 1;

dgtsv(@mI1@, @nI3@, @I0@, @I1@, @I2@, @I3@, &ldb, @O4@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;

@O1@ = @I1@;
*@mO1@ = *@mI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;

@O3@ = @I3@;
*@nO3@ = *@nI3@;
*@mO3@ = *@mI3@;

@END_CODE

#
# dgesv
#

@PROBLEM dgesv
@FUNCTION dgesv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Linear_Equations/
@DESCRIPTION
From LAPACK -

Compute the solution to a real system of linear equations
  A * X = b
where A is an N-by-B matrix and X and B are N-by-NRHS matrices.

MATLAB Example : [x y z info ] = netsolve('dgesv',a,b)

http://www.netlib.org/lapack/
@INPUT 2
@OBJECT MATRIX D a
Matrix A
@OBJECT MATRIX D b
Right hand side

@OUTPUT 4
@OBJECT MATRIX D lu
LU factors ( A = P*L*U)
@OBJECT VECTOR I ipiv
Vector of pivots (defines the P matrix)
@OBJECT MATRIX D x
Solution
@OBJECT SCALAR I info
INFO
  0  successful
  <0 error on calling ?
  >0 QR algorithm failed

@COMPLEXITY 2,3

@CALLINGSEQUENCE
@ARG mI0,nI0,mI1
@ARG nI1
@ARG I0,O0
@ARG lI0
@ARG O1
@ARG I1,O2
@ARG lI1
@ARG O3
@CODE
extern void dgesv(int *n, int *nrhs, double *a, int *lda, int *ipiv,
                  double *b, int *ldb, int *info);

int lda, ldb;

lda =ldb = (*@mI0@ > 1) ? *@mI0@ : 1;

if (*@nI0@ != *@mI0@)
  return NS_PROT_DIM_MISMATCH;
if (*@mI0@ != *@mI1@)
  return NS_PROT_DIM_MISMATCH;

@O1@ = (int *)malloc(sizeof(int)*(*@mI0@));
*@mO1@ = *@mI1@;
@O3@ = (int *)malloc(sizeof(int));

dgesv(@nI0@, @nI1@, @I0@, &lda, @O1@, @I1@, &ldb, @O3@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;
*@nO0@ = *@nI0@;
@O2@ = @I1@;
*@mO2@ = *@mI1@;
*@nO2@ = *@nI1@;
@END_CODE
#
# Double type LAPACK routines:  Simple and Divide-and-Conquer Drivers
#                               for Standard and Generalized Linear
#                               Least Squares Problems
#
# This file includes problem specifications for the following:
#
# DGGLSE
# DGGGLM
# DGELSS
# DGELSD
# DGELSX
# DGELSY
# DGELS

#
# DGGLSE
#
@PROBLEM dgglse
@FUNCTION dgglse
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGGLSE solves the linear equality-constrained least squares (LSE)
problem:

        minimize || c - A*x ||_2   subject to   B*x = d

where A is an M-by-N matrix, B is a P-by-N matrix, c is a given
M-vector, and d is a given P-vector. It is assumed that
P <= N <= M+P, and

         rank(B) = P and  rank( ( A ) ) = N.
                              ( ( B ) )

These conditions ensure that the LSE problem has a unique solution,
which is obtained using a GRQ factorization of the matrices B and A.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT MATRIX D a
A       (input) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input) DOUBLE PRECISION array, dimension (LDB,N)
        On entry, the P-by-N matrix B.
@OBJECT VECTOR D c
C       (input/output) DOUBLE PRECISION array, dimension (M)
        On entry, C contains the right hand side vector for the
        least squares part of the LSE problem.
@OBJECT VECTOR D d
D       (input) DOUBLE PRECISION array, dimension (P)
        On entry, D contains the right hand side vector for the
        constrained equation.
@OUTPUT 3
@OBJECT VECTOR D c
C       (input/output) DOUBLE PRECISION array, dimension (M)
        On exit, the residual sum of squares for the solution
        is given by the sum of squares of elements N-P+1 to M of
        vector C.
@OBJECT VECTOR D x
X       (output) DOUBLE PRECISION array, dimension (N)
        On exit, X is the solution of the LSE problem.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit.
        < 0:  if INFO = -i, the i-th argument had an illegal value.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI0,mI2 
@ARG nI0,nI1
@ARG mI1,mI3
@ARG I0
@ARG lI0
@ARG I1
@ARG lI1
@ARG I2,O0
@ARG I3
@ARG O1
@ARG ?
@ARG ?
@ARG O2
@CODE
extern void dgglse(int *m, int *n, int *p, double *a, int *lda, double *b,
                   int *ldb, double *c, double *d, double *x, double *work,
                   int *lwork, int *info);

int lda, ldb, lwork;
double *work;

if (*@mI0@ != *@mI2@ || 
    *@nI0@ != *@nI1@ || 
    *@mI1@ != *@mI3@) 
   return NS_PROT_DIM_MISMATCH;

lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@mI1@ > 1) ? *@nI1@ : 1;

lwork = *@mI0@ + *@nI0@ + *@nI1@;
if (lwork < 1) lwork = 1;
lwork *= 4;
work = (double *) malloc(sizeof(double) * lwork);

@O1@ = (double *) malloc(sizeof(double) * *@nI0@);
*@mO1@ = *@nI0@;
@O2@ = (int *) malloc(sizeof(int));

dgglse(@mI0@, @nI0@, @mI1@, @I0@, &lda, @I1@, &ldb,
       @I2@, @I3@, @O1@, work, &lwork, @O2@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
@END_CODE

#
# DGGGLM
#
@PROBLEM dggglm
@FUNCTION dggglm
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGGGLM solves a general Gauss-Markov linear model (GLM) problem:

        minimize || y ||_2   subject to   d = A*x + B*y
            x

where A is an N-by-M matrix, B is an N-by-P matrix, and d is a
given N-vector. It is assumed that M <= N <= M+P, and

           rank(A) = M    and    rank( A B ) = N.

Under these assumptions, the constrained equation is always
consistent, and there is a unique solution x and a minimal 2-norm
solution y, which is obtained using a generalized QR factorization
of A and B.

In particular, if matrix B is square nonsingular, then the problem
GLM is equivalent to the following weighted linear least squares
problem

             minimize || inv(B)*(d-A*x) ||_2
                 x

where inv(B) denotes the inverse of B.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,M)
        On entry, the N-by-M matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,P)
        On entry, the N-by-P matrix B.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On entry, D is the left hand side of the GLM equation.
@OUTPUT 6
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,M)
        On exit, A is destroyed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,P)
        On exit, B is destroyed.
@OBJECT VECTOR D d
D       (input/output) DOUBLE PRECISION array, dimension (N)
        On exit, D is destroyed.
@OBJECT VECTOR D x
X       (output) DOUBLE PRECISION array, dimension (M)
@OBJECT VECTOR D y
Y       (output) DOUBLE PRECISION array, dimension (P)
        On exit, X and Y are the solutions of the GLM problem.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit.
        < 0:  if INFO = -i, the i-th argument had an illegal value.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI2,mI0,mI1
@ARG nI0
@ARG nI1
@ARG I0,O0
@ARG lI0
@ARG I1,O1
@ARG lI1
@ARG I2,O2
@ARG O3
@ARG O4
@ARG ?
@ARG ?
@ARG O5
@CODE
extern void dggglm(int *n, int *m, int *p, double *a, int *lda, double *b,
                   int *ldb, double *d, double *x, double *y, double *work,
                   int *lwork, int *info);

int lwork, lda, ldb;
double *work;

if (*@mI2@ != *@mI0@ || *@mI0@ != *@mI1@) return NS_PROT_DIM_MISMATCH;

lwork = *@mI2@ + *@nI0@ + *@nI1@;
lwork = abs(lwork) + 1;
lwork *= 2;

work = (double *) malloc(sizeof(double) * lwork);

lda = ldb = (*@mI2@ > 1) ? *@mI2@ : 1;

@O3@ = (double *) malloc(sizeof(double) * *@nI0@);
@O4@ = (double *) malloc(sizeof(double) * *@nI1@);
@O5@ = (int *) malloc(sizeof(int));

dggglm(@mI2@, @nI0@, @nI1@, @I0@, &lda, @I1@, &ldb,           
       @I2@, @O3@, @O4@, work, &lwork, @O5@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;
*@nO0@ = *@nI0@;

@O1@ = @I1@;
*@mO1@ = *@mI1@;
*@nO1@ = *@nI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;

*@mO3@ = *@nI0@;
*@mO4@ = *@nI1@;

@END_CODE


#
# DGELSS
#
@PROBLEM dgelss
@FUNCTION dgelss
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGELSS computes the minimum norm solution to a real linear least
squares problem:

Minimize 2-norm(| b - A*x |).

using the singular value decomposition (SVD) of A. A is an M-by-N
matrix which may be rank-deficient.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
X.

The effective rank of A is determined by treating as zero those
singular values which are less than RCOND times the largest singular
value.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the M-by-NRHS right hand side matrix B.
@OBJECT SCALAR D rcond
RCOND   (input) DOUBLE PRECISION
        RCOND is used to determine the effective rank of A.
        Singular values S(i) <= RCOND*S(1) are treated as zero.
        If RCOND < 0, machine precision is used instead.
@OUTPUT 5
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, the first min(m,n) rows of A are overwritten with
        its right singular vectors, stored rowwise.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, B is overwritten by the N-by-NRHS solution
        matrix X.  If m >= n and RANK = n, the residual
        sum-of-squares for the solution in the i-th column is given
        by the sum of squares of elements n+1:m in that column.
@OBJECT VECTOR D s
S       (output) DOUBLE PRECISION array, dimension (min(M,N))
        The singular values of A in decreasing order.
        The condition number of A in the 2-norm = S(1)/S(min(m,n)).
@OBJECT SCALAR I rank
RANK    (output) INTEGER
        The effective rank of A, i.e., the number of singular values
        which are greater than RCOND*S(1).
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  the algorithm for computing the SVD failed to converge;
              if INFO = i, i off-diagonal elements of an intermediate
              bidiagonal form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI0,mI1
@ARG nI0
@ARG nI1
@ARG I0,O0
@ARG lI0
@ARG I1,O1
@ARG lI1
@ARG O2
@ARG I2
@ARG O3
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dgelss(int *m, int *n, int *nrhs, double *a, int *lda,
                   double *b, int *ldb, double *s, double *rcond,
                   int *rank, double *work, int *lwork, int *info);

int lda, ldb;
int lwork, scratch;
double *work;

if (*@mI0@ != *@mI1@) return NS_PROT_DIM_MISMATCH;

lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@nI0@ > lda) ? *@nI0@ : lda;

lwork = (2 * ldb > *@nI1@) ? 2 * ldb : *@nI1@;
lwork += 3 * ldb;

scratch = (*@mI0@ > *@nI0@) ? *@nI0@ : *@mI0@;

work = (double *) malloc(sizeof(double) * lwork);
@O2@ = (double *) malloc(sizeof(double) * scratch);
@O3@ = (int *) malloc(sizeof(int));
@O4@ = (int *) malloc(sizeof(int));


dgelss(@mI0@, @nI0@, @nI1@, @I0@, &lda, @I1@, &ldb, @O2@, @I2@, @O3@, 
       work, &lwork, @O4@);

@O0@ = @I0@;
*@mO0@ = *@mO0@;
*@nO0@ = *@nO0@;

@O1@ = @I1@;
*@mO1@ = *@nI0@;
*@nO1@ = *@nI1@;

*@mO2@ = (*@mI0@ > *@nI0@) ?  *@nI0@ : *@mI0@;
@END_CODE

#
# DGELSD
#
@PROBLEM dgelsd
@FUNCTION dgelsd
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGELSD computes the minimum-norm solution to a real linear least
squares problem:
    minimize 2-norm(| b - A*x |)
using the singular value decomposition (SVD) of A. A is an M-by-N
matrix which may be rank-deficient.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.

The problem is solved in three steps:
(1) Reduce the coefficient matrix A to bidiagonal form with
    Householder transformations, reducing the original problem
    into a "bidiagonal least squares problem" (BLS)
(2) Solve the BLS using a divide and conquer approach.
(3) Apply back all the Householder tranformations to solve
    the original least squares problem.

The effective rank of A is determined by treating as zero those
singular values which are less than RCOND times the largest singular
value.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT MATRIX D a
A       (input) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the M-by-NRHS right hand side matrix B.
@OBJECT SCALAR D rcond
RCOND   (input) DOUBLE PRECISION
        RCOND is used to determine the effective rank of A.
        Singular values S(i) <= RCOND*S(1) are treated as zero.
        If RCOND < 0, machine precision is used instead.
@OUTPUT 4
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, B is overwritten by the N-by-NRHS solution
        matrix X.  If m >= n and RANK = n, the residual
        sum-of-squares for the solution in the i-th column is given
        by the sum of squares of elements n+1:m in that column.
@OBJECT VECTOR D s
S       (output) DOUBLE PRECISION array, dimension (min(M,N))
        The singular values of A in decreasing order.
        The condition number of A in the 2-norm = S(1)/S(min(m,n)).
@OBJECT SCALAR I rank
RANK    (output) INTEGER
        The effective rank of A, i.e., the number of singular values
        which are greater than RCOND*S(1).
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  the algorithm for computing the SVD failed to converge;
              if INFO = i, i off-diagonal elements of an intermediate
              bidiagonal form did not converge to zero.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI0,mI1
@ARG nI0
@ARG nI1
@ARG I0
@ARG lI0
@ARG I1,O0
@ARG lI1
@ARG O1
@ARG I2
@ARG O2
@ARG ?
@ARG ?
@ARG ?
@ARG O3
@CODE
extern void dgelsd(int *m, int *n, int *nrhs, double *a, int *lda,
                   double *b, int *ldb, double *s, double *rcond,
                   int *rank, double *work, int *lwork, int *iwork,
                   int *info);

int lda, ldb;
int lwork, liwork, minmn, nlvl, scratch, smlsiz;
double *work;
int *iwork;
/*
int nine = 9;
int zero = 0;
*/
unsigned int arg;
/*
extern int ilaenv();
*/

if (*@mI0@ != *@mI1@) return NS_PROT_DIM_MISMATCH;

lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@nI0@ > lda) ? *@nI0@ : lda;

/*
smlsiz = ilaenv( &nine, "dgelsd", " ", &zero, &zero, &zero, &zero );
*/
smlsiz = 25;
minmn = (*@mI0@ < *@nI0@) ? *@mI0@ : *@nI0@;
scratch = 0;
arg = minmn/(smlsiz+1);
while (arg > 1) {
    arg >>= 1;
    scratch++;
  }
scratch += 1;
nlvl = ( scratch > 0 ) ? scratch : 0;

if (*@mI0@ >= *@nI0@) {
   lwork = 12 * *@nI0@ + 2 * *@nI0@ * smlsiz + 8 * *@nI0@ * nlvl
           + *@nI0@ * *@nI1@ + (smlsiz+1)*(smlsiz+1); 
} else {
   lwork = 12 * *@mI0@ + 2 * *@mI0@ * smlsiz + 8 * *@mI0@ * nlvl
           + *@mI0@ * *@nI1@ + (smlsiz+1)*(smlsiz+1); 
}

liwork = 3 * minmn * nlvl + 11 * minmn;
work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);
@O1@ = (double *) malloc(sizeof(double) * minmn);
@O2@ = (int *) malloc(sizeof(int));
@O3@ = (int *) malloc(sizeof(int));


dgelsd(@mI0@, @nI0@, @nI1@, @I0@, &lda, @I1@, &ldb, @O1@, @I2@, @O2@, 
       work, &lwork, iwork, @O3@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

*@mO1@ = (*@mI0@ > *@nI0@) ?  *@nI0@ : *@mI0@;
@END_CODE


#
# DGELSX
#
@PROBLEM dgelsx
@FUNCTION dgelsx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGELSX computes the minimum-norm solution to a real linear least
squares problem:
    minimize || A * X - B ||
using a complete orthogonal factorization of A.  A is an M-by-N
matrix which may be rank-deficient.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.

The routine first computes a QR factorization with column pivoting:
    A * P = Q * [ R11 R12 ]
                [  0  R22 ]
with R11 defined as the largest leading submatrix whose estimated
condition number is less than 1/RCOND.  The order of R11, RANK,
is the effective rank of A.

Then, R22 is considered to be negligible, and R12 is annihilated
by orthogonal transformations from the right, arriving at the
complete orthogonal factorization:
   A * P = Q * [ T11 0 ] * Z
               [  0  0 ]
The minimum-norm solution is then
   X = P * Z' [ inv(T11)*Q1'*B ]
              [        0       ]
where Q1 consists of the first RANK columns of Q.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the M-by-NRHS right hand side matrix B.
@OBJECT VECTOR I jpvt
JPVT    (input/output) INTEGER array, dimension (N)
        On entry, if JPVT(i) .ne. 0, the i-th column of A is an
        initial column, otherwise it is a free column.  Before
        the QR factorization of A, all initial columns are
        permuted to the leading positions; only the remaining
        free columns are moved as a result of column pivoting
        during the factorization.
@OBJECT SCALAR D rcond
RCOND   (input) DOUBLE PRECISION
        RCOND is used to determine the effective rank of A, which
     is defined as the order of the largest leading triangular
        submatrix R11 in the QR factorization with pivoting of A,
        whose estimated condition number < 1/RCOND.
@OUTPUT 5
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, A has been overwritten by details of its
        complete orthogonal factorization.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, the N-by-NRHS solution matrix X.
        If m >= n and RANK = n, the residual sum-of-squares for
        the solution in the i-th column is given by the sum of
        squares of elements N+1:M in that column.
@OBJECT VECTOR I jpvt
JPVT    (input/output) INTEGER array, dimension (N)
        On exit, if JPVT(i) = k, then the i-th column of A*P
        was the k-th column of A.
@OBJECT SCALAR I rank
RANK    (output) INTEGER
        The effective rank of A, i.e., the order of the submatrix
        R11.  This is the same as the order of the submatrix T11
        in the complete orthogonal factorization of A.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI0,mI1
@ARG nI0,mI2
@ARG nI1
@ARG I0,O0
@ARG lI0
@ARG I1,O1
@ARG lI1
@ARG I2,O2
@ARG I3
@ARG O3
@ARG ?
@ARG O4
@CODE
extern void dgelsx(int *m, int *n, int *nrhs,
        double *a, int *lda, double *b, int *ldb, int *jpvt,
        double *rcond, int *rank, double *work, int *info);

int lda, ldb, lwork, minmn;
double *work;
int scratcha, scratchb;

if (*@mI0@ != *@mI1@) return NS_PROT_DIM_MISMATCH;

if (*@nI0@ != *@mI2@) return NS_PROT_DIM_MISMATCH;


lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@nI0@ > lda) ? *@nI0@ : lda;

@O3@ = (double *) malloc(sizeof(double));
@O4@ = (int *) malloc(sizeof(int));

minmn = (*@mI0@ > *@nI0@) ? *@nI0@ : *@mI0@;
scratcha = minmn + 3 * *@nI0@;
scratchb = 2 * minmn + *@nI1@;
lwork = (scratcha > scratchb) ? scratcha : scratchb;

work = (double *) malloc(sizeof(double) * lwork);

dgelsx(@mI0@, @nI0@, @nI1@, @I0@, &lda, @I1@,
       &ldb, @I2@, @I3@, @O3@, work, @O4@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;
*@nO0@ = *@nI0@;

@O1@ = @I1@;
*@mO1@ = *@mI1@;
*@nO1@ = *@nI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;

@END_CODE

#
# DGELSY
#
@PROBLEM dgelsy
@FUNCTION dgelsy
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGELSY computes the minimum-norm solution to a real linear least
  squares problem:
      minimize || A * X - B ||
  using a complete orthogonal factorization of A.  A is an M-by-N
  matrix which may be rank-deficient.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.

The routine first computes a QR factorization with column pivoting:
    A * P = Q * [ R11 R12 ]
                [  0  R22 ]
with R11 defined as the largest leading submatrix whose estimated
condition number is less than 1/RCOND.  The order of R11, RANK,
is the effective rank of A.

Then, R22 is considered to be negligible, and R12 is annihilated
by orthogonal transformations from the right, arriving at the
complete orthogonal factorization:
   A * P = Q * [ T11 0 ] * Z
               [  0  0 ]
The minimum-norm solution is then
   X = P * Z' [ inv(T11)*Q1'*B ]
              [        0       ]
where Q1 consists of the first RANK columns of Q.

This routine is basically identical to the original xGELSX except
three differences:
  o The call to the subroutine xGEQPF has been substituted by the
    the call to the subroutine xGEQP3. This subroutine is a Blas-3
    version of the QR factorization with column pivoting.
  o Matrix B (the right hand side) is updated with Blas-3.
  o The permutation of matrix B (the right hand side) is faster and
    more simple.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the M-by-NRHS right hand side matrix B.
@OBJECT VECTOR I jpvt
JPVT    (input/output) INTEGER array, dimension (N)
        On entry, if JPVT(i) .ne. 0, the i-th column of A is an
        initial column, otherwise it is a free column.  Before
        the QR factorization of A, all initial columns are
        permuted to the leading positions; only the remaining
        free columns are moved as a result of column pivoting
        during the factorization.
@OBJECT SCALAR D rcond
RCOND   (input) DOUBLE PRECISION
        RCOND is used to determine the effective rank of A, which
     is defined as the order of the largest leading triangular
        submatrix R11 in the QR factorization with pivoting of A,
        whose estimated condition number < 1/RCOND.
@OUTPUT 5
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, A has been overwritten by details of its
        complete orthogonal factorization.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, the N-by-NRHS solution matrix X.
        If m >= n and RANK = n, the residual sum-of-squares for
        the solution in the i-th column is given by the sum of
        squares of elements N+1:M in that column.
@OBJECT VECTOR I jpvt
JPVT    (input/output) INTEGER array, dimension (N)
        On exit, if JPVT(i) = k, then the i-th column of A*P
        was the k-th column of A.
@OBJECT SCALAR I rank
RANK    (output) INTEGER
        The effective rank of A, i.e., the order of the submatrix
        R11.  This is the same as the order of the submatrix T11
        in the complete orthogonal factorization of A.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG mI0,mI1
@ARG nI0,mI2
@ARG nI1
@ARG I0,O0
@ARG lI0
@ARG I1,O1
@ARG lI1
@ARG I2,O2
@ARG I3
@ARG O3
@ARG ?
@ARG ?
@ARG O4
@CODE
extern void dgelsy(int *m, int *n, int *nrhs, double *a, int *lda,
                   double *b, int *ldb, int * jpvt, double *rcond,
                   int *rank, double *work, int *lwork, int *info);

int lda, ldb, lwork, minmn, nb;
/*
int one = 1;
int minusone = -1;
*/
double *work;
int scratcha, scratchb;

/*
extern int ilaenv();
*/

if (*@mI0@ != *@mI1@) return NS_PROT_DIM_MISMATCH;

if (*@nI0@ != *@mI2@) return NS_PROT_DIM_MISMATCH;


lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@nI0@ > lda) ? *@nI0@ : lda;

@O3@ = (double *) malloc(sizeof(double));
@O4@ = (int *) malloc(sizeof(int));

minmn = (*@mI0@ > *@nI0@) ? *@nI0@ : *@mI0@;
/*
nb1 = ilaenv( &one, "dgeqrf", " ", *@mI0@, *@nI0@, &minusone, &minusone ); 
nb2 = ilaenv( &one, "dgerqf", " ", *@mI0@, *@nI0@, &minusone, &minusone ); 
nb3 = ilaenv( &one, "dormqr", " ", *@mI0@, *@nI0@, *@nI1@, &minusone ); 
nb4 = ilaenv( &one, "dormrq", " ", *@mI0@, *@nI0@, *@nI1@, &minusone ); 
nb = (nb1 > nb2) ? nb1 : nb2;
nb = (nb > nb3) ? nb : nb3;
nb = (nb > nb4) ? nb : nb4;
*/
nb = 64;
scratcha = minmn + 2 * *@nI0@ + nb * ( *@nI0@ + 1 );
scratchb = 2 * minmn + nb * *@nI1@;
lwork = (scratcha > scratchb) ? scratcha : scratchb;

work = (double *) malloc(sizeof(double) * lwork);

dgelsy(@mI0@, @nI0@, @nI1@, @I0@, &lda, @I1@, &ldb, 
       @I2@, @I3@, @O3@, work, &lwork, @O4@);

@O0@ = @I0@;
*@mO0@ = *@mI0@;
*@nO0@ = *@nI0@;

@O1@ = @I1@;
*@mO1@ = *@mI1@;
*@nO1@ = *@nI1@;

@O2@ = @I2@;
*@mO2@ = *@mI2@;

@END_CODE

#
# DGELS 
#
@PROBLEM dgels
@FUNCTION dgels
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Least_Squares/
@DESCRIPTION
DGELS solves overdetermined or underdetermined real linear systems
involving an M-by-N matrix A, or its transpose, using a QR or LQ
factorization of A.  It is assumed that A has full rank.

The following options are provided:

1. If TRANS = 'N' and m >= n:  find the least squares solution of
   an overdetermined system, i.e., solve the least squares problem
                minimize || B - A*X ||.

2. If TRANS = 'N' and m < n:  find the minimum norm solution of
   an underdetermined system A * X = B.

3. If TRANS = 'T' and m >= n:  find the minimum norm solution of
   an undetermined system A**T * X = B.

4. If TRANS = 'T' and m < n:  find the least squares solution of
   an overdetermined system, i.e., solve the least squares problem
                minimize || B - A**T * X ||.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.
http://www.netlib.org/lapack/
@INPUT 3
@OBJECT SCALAR CHAR trans
TRANS   (input) CHARACTER
        = 'N': the linear system involves A;
        = 'T': the linear system involves A**T.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On entry, the matrix B of right hand side vectors, stored
        columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS
        if TRANS = 'T'.
@OUTPUT 3
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit,
          if M >= N, A is overwritten by details of its QR
                     factorization as returned by DGEQRF;
          if M <  N, A is overwritten by details of its LQ
                     factorization as returned by DGELQF.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
        On exit, B is overwritten by the solution vectors, stored
        columnwise:
        if TRANS = 'N' and m >= n, rows 1 to n of B contain the least
        squares solution vectors; the residual sum of squares for the
        solution in each column is given by the sum of squares of
        elements N+1 to M in that column;
        if TRANS = 'N' and m < n, rows 1 to N of B contain the
        minimum norm solution vectors;
        if TRANS = 'T' and m >= n, rows 1 to M of B contain the
        minimum norm solution vectors;
        if TRANS = 'T' and m < n, rows 1 to M of B contain the
        least squares solution vectors; the residual sum of squares
        for the solution in each column is given by the sum of
        squares of elements M+1 to N in that column.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# TRANS, char
@ARG I0
# m, rows of A
@ARG mI1
# n, cols of A
@ARG nI1
# nrhs, cols of B and X
@ARG nI2
# A
@ARG I1,O0
# lda
@ARG lI1
# B
@ARG I2,O1
# ldb
@ARG lI2
@ARG ?
@ARG ?
# info
@ARG O2
@COMP mI2=if(array(I0,0)='N',mI1,if(array(I0,0)='T',nI1,op(-,0,1)))
@CODE
extern void dgels(char *trans, int *m, int *n, int *nrhs, double *a,
                  int *lda, double *b, int *ldb, double *work, int *lwork,
                  int *info);

int lda, ldb, nb;
int lwork, scratch = 1;
double *work;
double *newb;
int i;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 't' || *@I0@ == 'T')
   *@I0@ = 'T';
else 
   return NS_PROT_BAD_VALUES;
@O2@ = (int *) malloc(sizeof(int));

if (*@mI2@ == -1)
  return NS_PROT_BAD_VALUES;

lwork = (*@mI1@ > *@nI1@) ?  *@nI1@ : *@mI1@;
if (*@mI1@ > scratch) scratch = *@mI1@;
if (*@nI1@ > scratch) scratch = *@nI1@;
if (*@nI2@ > scratch) scratch = *@nI2@;
nb = 64;
scratch *= nb; 
lwork += scratch;

work = (double *) malloc(sizeof(double) * lwork);

lda = (*@mI1@ > 1) ? *@mI1@ : 1;

ldb = 1;
if (*@mI1@ > ldb) ldb = *@mI1@;
if (*@nI1@ > ldb) ldb = *@nI1@;

newb = (double *)malloc(sizeof(double)*ldb*(*@nI2@));
for (i=0;i<*@nI2@;i++)
 bcopy(&(@I2@[i*(*@mI2@)]),&(newb[i*ldb]),sizeof(double)*(*@mI2@));


dgels(@I0@, @mI1@, @nI1@, @nI2@, @I1@, &lda, newb, &ldb, work, &lwork, @O2@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

@O1@ = newb;
*@mO1@ = ldb;
*@nO1@ = *@nI2@;

@END_CODE
#
# Double type LAPACK routines:  Simple and Divide and Conquer Driver
#                               Routines for Generalized Eigenvalue and
#                               Singular Value Problems
# 
# 
# DGGSVD
# DGEGV
# DGGEV
# DGEGS
# DSBGV
# DSBGVD
# DSBGVX
# DSYGV
# DSYGVD
# DSYGVX
#


#
# DGGSVD
#
@PROBLEM dggsvd
@FUNCTION dggsvd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DGGSVD computes the generalized singular value decomposition (GSVD)
of an M-by-N real matrix A and P-by-N real matrix B:

    U'*A*Q = D1*( 0 R ),    V'*B*Q = D2*( 0 R )

where U, V and Q are orthogonal matrices, and Z' is the transpose
of Z.  Let K+L = the effective numerical rank of the matrix (A',B')',
then R is a K+L-by-K+L nonsingular upper triangular matrix, D1 and
D2 are M-by-(K+L) and P-by-(K+L) "diagonal" matrices and of the
following structures, respectively:

If M-K-L >= 0,

                    K  L
       D1 =     K ( I  0 )
                L ( 0  C )
            M-K-L ( 0  0 )

                  K  L
       D2 =   L ( 0  S )
            P-L ( 0  0 )

                N-K-L  K    L
  ( 0 R ) = K (  0   R11  R12 )
            L (  0    0   R22 )

where

  C = diag( ALPHA(K+1), ... , ALPHA(K+L) ),
  S = diag( BETA(K+1),  ... , BETA(K+L) ),
  C**2 + S**2 = I.

  R is stored in A(1:K+L,N-K-L+1:N) on exit.

If M-K-L < 0,

                  K M-K K+L-M
       D1 =   K ( I  0    0   )
            M-K ( 0  C    0   )

                    K M-K K+L-M
       D2 =   M-K ( 0  S    0  )
            K+L-M ( 0  0    I  )
              P-L ( 0  0    0  )

                   N-K-L  K   M-K  K+L-M
  ( 0 R ) =     K ( 0    R11  R12  R13  )
              M-K ( 0     0   R22  R23  )
            K+L-M ( 0     0    0   R33  )

where

  C = diag( ALPHA(K+1), ... , ALPHA(M) ),
  S = diag( BETA(K+1),  ... , BETA(M) ),
  C**2 + S**2 = I.

  (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), and R33 is stored
  ( 0  R22 R23 )
  in B(M-K+1:L,N+M-K-L+1:N) on exit.
The routine computes C, S, R, and optionally the orthogonal
transformation matrices U, V and Q.

In particular, if B is an N-by-N nonsingular matrix, then the GSVD of
A and B implicitly gives the SVD of A*inv(B):
                     A*inv(B) = U*(D1*inv(D2))*V'.
If ( A',B')' has orthonormal columns, then the GSVD of A and B is
also equal to the CS decomposition of A and B. Furthermore, the GSVD
can be used to derive the solution of the eigenvalue problem:
                     A'*A x = lambda* B'*B x.
In some literature, the GSVD of A and B is presented in the form
                 U'*A*X = ( 0 D1 ),   V'*B*X = ( 0 D2 )
where U and V are orthogonal and X is nonsingular, D1 and D2 are
``diagonal''.  The former GSVD form can be converted to the latter
form by taking the nonsingular matrix X as

                     X = Q*( I   0    )
                           ( 0 inv(R) ).
http://www.netlib.org/lapack/
@INPUT 5
@OBJECT SCALAR CHAR jobu
JOBU    (input) CHARACTER*1
        = 'U':  Orthogonal matrix U is computed;
        = 'N':  U is not computed.
@OBJECT SCALAR CHAR jobv
JOBV    (input) CHARACTER*1
        = 'V':  Orthogonal matrix V is computed;
        = 'N':  V is not computed.
@OBJECT SCALAR CHAR jobq
JOBQ    (input) CHARACTER*1
        = 'Q':  Orthogonal matrix Q is computed;
        = 'N':  Q is not computed.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On entry, the M-by-N matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
        On entry, the P-by-N matrix B.
@OUTPUT 10
@OBJECT SCALAR I k
K       (output) INTEGER
@OBJECT SCALAR I l
L       (output) INTEGER
        On exit, K and L specify the dimension of the subblocks
        described in the Purpose section.
        K + L = effective numerical rank of (A',B')'.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        On exit, A contains the triangular matrix R, or part of R.
        See Purpose for details.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
        On exit, B contains the triangular matrix R if M-K-L < 0.
        See Purpose for details.
@OBJECT VECTOR D alpha
ALPHA   (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D beta
BETA    (output) DOUBLE PRECISION array, dimension (N)
        On exit, ALPHA and BETA contain the generalized singular
        value pairs of A and B;
          ALPHA(1:K) = 1,
          BETA(1:K)  = 0,
        and if M-K-L >= 0,
          ALPHA(K+1:K+L) = C,
          BETA(K+1:K+L)  = S,
        or if M-K-L < 0,
          ALPHA(K+1:M)=C, ALPHA(M+1:K+L)=0
          BETA(K+1:M) =S, BETA(M+1:K+L) =1
        and
          ALPHA(K+L+1:N) = 0
          BETA(K+L+1:N)  = 0
@OBJECT MATRIX D u
U       (output) DOUBLE PRECISION array, dimension (LDU,M)
        If JOBU = 'U', U contains the M-by-M orthogonal matrix U.
        If JOBU = 'N', U is not referenced.
@OBJECT MATRIX D v
V       (output) DOUBLE PRECISION array, dimension (LDV,P)
        If JOBV = 'V', V contains the P-by-P orthogonal matrix V.
        If JOBV = 'N', V is not referenced.
@OBJECT MATRIX D q
Q       (output) DOUBLE PRECISION array, dimension (LDQ,N)
        If JOBQ = 'Q', Q contains the N-by-N orthogonal matrix Q.
        If JOBQ = 'N', Q is not referenced.
@OBJECT SCALAR I info
INFO    (output)INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        > 0:  if INFO = 1, the Jacobi-type procedure failed to
              converge.  For further details, see subroutine DTGSJA.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG mI3
@ARG nI3,nI4
@ARG mI4
# K, L
@ARG O0
@ARG O1
# A
@ARG I3,O2
@ARG lI3,lO2
# B
@ARG I4,O3
@ARG lI4,lO3
@ARG O4
@ARG O5
@ARG O6
@ARG lO6
@ARG O7
@ARG lO7
@ARG O8
@ARG lO8
@ARG ?
@ARG ?
@ARG O9
@CODE
extern void dggsvd(char *jobu, char *jobv, char *jobq, int *m,
                   int *n, int *p, int *k, int *l, double *a,
                   int *lda, double *b, int *ldb, double *alpha,
                   double *beta, double *u, int *ldu, double *v, int *ldv,
                   double *q, int *ldq, double *work, int *iwork, int *info);

int lda, ldb, ldu = 1, ldv = 1, ldq = 1, *iwork;
int lwork;
double *work;

if (*@I0@ == 'u' || *@I0@ == 'U')
   *@I0@ = 'U';
else if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'n' || *@I1@ == 'N')
   *@I1@ = 'N';
else
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'q' || *@I2@ == 'Q')
   *@I2@ = 'Q';
else if (*@I2@ == 'n' || *@I2@ == 'N')
   *@I2@ = 'N';
else
   return NS_PROT_BAD_VALUES;

#if (*@nI3@ != *@nI4@) return NS_PROT_DIM_MISMATCH;

lda = *@mI3@ > 1 ? *@mI3@ : 1;
ldb = *@mI4@ > 1 ? *@mI4@ : 1;

iwork = (int *) malloc(sizeof(int) * *@nI3@);
lwork = *@mI4@;
if (3 * *@nI3@ > lwork) lwork = 3 * *@nI3@;
if (*@mI3@ > lwork) lwork = *@mI3@;
lwork += *@nI3@;
work = (double *) malloc(sizeof(double) * lwork);

@O0@ = (int *) malloc(sizeof(int));
@O1@ = (int *) malloc(sizeof(int));

@O4@ = (double *) malloc(sizeof(double) * *@nI3@);
@O5@ = (double *) malloc(sizeof(double) * *@nI3@);
*@mO4@ = *@nI3@;
*@mO5@ = *@nI3@;

if (*@I0@ == 'U') {
   if (ldu < *@mI3@) ldu = *@mI3@;
   @O6@ = (double *) malloc(sizeof(double) * *@mI3@ * ldu);
   *@mO6@ = ldu;
   *@nO6@ = *@mI3@;
} else {
   @O6@ = (double *) malloc(sizeof(double));
   *@mO6@ = ldu;
   *@nO6@ = 1;
}
  
if (*@I1@ == 'V') {
   if (*@mI4@ > ldv) ldv = *@mI4@;
   @O7@ = (double *) malloc(sizeof(double) * *@mI4@ * ldv);
   *@mO7@ = ldv;
   *@nO7@ = *@mI4@;
} else {
   @O7@ = (double *) malloc(sizeof(double));
   *@mO7@ = ldv;
   *@nO7@ = 1;
}

if (*@I2@ == 'Q') {
   if (*@nI3@ > ldq) ldq = *@nI3@;
   @O8@ = (double *) malloc(sizeof(double) * *@nI3@ * ldq);
   *@mO8@ = ldq;
   *@nO8@ = *@nI3@;
} else {
   @O8@ = (double *) malloc(sizeof(double));
   *@mO8@ = ldq;
   *@nO8@ = 1;
}

@O9@ = (int *) malloc(sizeof(int));

dggsvd(@I0@, @I1@, @I2@, @mI3@, @nI3@, @mI4@, @O0@, @O1@, @I3@, &lda,
       @I4@, &ldb, @O4@, @O5@, @O6@, &ldu, @O7@, &ldv, @O8@, &ldq,
       work, iwork, @O9@);

@O2@ = @I3@;
*@mO2@ = *@mI3@;
*@nO2@ = *@nI3@;

@O3@ = @I4@;
*@mO3@ = *@mI4@;
*@nO3@ = *@nI4@;
@END_CODE


#
# DGEGV
#
@PROBLEM dgegv
@FUNCTION dgegv
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
This routine is deprecated and has been replaced by routine DGGEV.

DGEGV computes for a pair of n-by-n real nonsymmetric matrices A and
B, the generalized eigenvalues (alphar +/- alphai*i, beta), and
optionally, the left and/or right generalized eigenvectors (VL and
VR).

A generalized eigenvalue for a pair of matrices (A,B) is, roughly
speaking, a scalar w or a ratio  alpha/beta = w, such that  A - w*B
is singular.  It is usually represented as the pair (alpha,beta),
as there is a reasonable interpretation for beta=0, and even for
both being zero.  A good beginning reference is the book, "Matrix
Computations", by G. Golub & C. van Loan (Johns Hopkins U. Press)

A right generalized eigenvector corresponding to a generalized
eigenvalue  w  for a pair of matrices (A,B) is a vector  r  such
that  (A - w B) r = 0 .  A left generalized eigenvector is a vector
l such that l**H * (A - w B) = 0, where l**H is the
conjugate-transpose of l.

Note: this routine performs "full balancing" on A and B -- see
"Further Details", below.
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR jobvl
JOBVL   (input) CHARACTER*1
        = 'N':  do not compute the left generalized eigenvectors;
        = 'V':  compute the left generalized eigenvectors.
@OBJECT SCALAR CHAR jobvr
JOBVR   (input) CHARACTER*1
        = 'N':  do not compute the right generalized eigenvectors;
        = 'V':  compute the right generalized eigenvectors.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the first of the pair of matrices whose
        generalized eigenvalues and (optionally) generalized
        eigenvectors are to be computed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On entry, the second of the pair of matrices whose
        generalized eigenvalues and (optionally) generalized
        eigenvectors are to be computed.
@OUTPUT 8
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, the contents will have been destroyed.  (For a
        description of the contents of A on exit, see "Further
        Details", below.)
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On exit, the contents will have been destroyed.  (For a
        description of the contents of B on exit, see "Further
        Details", below.)
@OBJECT VECTOR D alphar
ALPHAR  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D alphai
ALPHAI  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D beta
BETA    (output) DOUBLE PRECISION array, dimension (N)
        On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will
        be the generalized eigenvalues.  If ALPHAI(j) is zero, then
        the j-th eigenvalue is real; if positive, then the j-th and
        (j+1)-st eigenvalues are a complex conjugate pair, with
        ALPHAI(j+1) negative.

        Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)
        may easily over- or underflow, and BETA(j) may even be zero.
        Thus, the user should avoid naively computing the ratio
        alpha/beta.  However, ALPHAR and ALPHAI will be always less
        than and usually comparable with norm(A) in magnitude, and
        BETA always less than and usually comparable with norm(B).
@OBJECT MATRIX D vl
VL      (output) DOUBLE PRECISION array, dimension (LDVL,N)
        If JOBVL = 'V', the left generalized eigenvectors.  (See
        "Purpose", above.)  Real eigenvectors take one column,
        complex take two columns, the first for the real part and
        the second for the imaginary part.  Complex eigenvectors
        correspond to an eigenvalue with positive imaginary part.
        Each eigenvector will be scaled so the largest component
        will have abs(real part) + abs(imag. part) = 1, *except*
        that for eigenvalues with alpha=beta=0, a zero vector will
        be returned as the corresponding eigenvector.
        Not referenced if JOBVL = 'N'.
@OBJECT MATRIX D vr
VR      (output) DOUBLE PRECISION array, dimension (LDVR,N)
        If JOBVR = 'V', the right generalized eigenvectors.  (See
        "Purpose", above.)  Real eigenvectors take one column,
        complex take two columns, the first for the real part and
        the second for the imaginary part.  Complex eigenvectors
        correspond to an eigenvalue with positive imaginary part.
        Each eigenvector will be scaled so the largest component
        will have abs(real part) + abs(imag. part) = 1, *except*
        that for eigenvalues with alpha=beta=0, a zero vector will
        be returned as the corresponding eigenvector.
        Not referenced if JOBVR = 'N'.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        = 1,...,N:
              The QZ iteration failed.  No eigenvectors have been
              calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)
              should be correct for j=INFO+1,...,N.
        > N:  errors that usually indicate LAPACK problems:
              =N+1: error return from DGGBAL
              =N+2: error return from DGEQRF
              =N+3: error return from DORMQR
              =N+4: error return from DORGQR
              =N+5: error return from DGGHRD
              =N+6: error return from DHGEQZ (other than failed
                                              iteration)
              =N+7: error return from DTGEVC
              =N+8: error return from DGGBAK (computing VL)
              =N+9: error return from DGGBAK (computing VR)
              =N+10: error return from DLASCL (various calls)
Further Details
===============
Balancing
---------

This driver calls DGGBAL to both permute and scale rows and columns
of A and B.  The permutations PL and PR are chosen so that PL*A*PR
and PL*B*R will be upper triangular except for the diagonal blocks
A(i:j,i:j) and B(i:j,i:j), with i and j as close together as
possible.  The diagonal scaling matrices DL and DR are chosen so
that the pair  DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to
one (except for the elements that start out zero.)

After the eigenvalues and eigenvectors of the balanced matrices
have been computed, DGGBAK transforms the eigenvectors back to what
they would have been (in perfect arithmetic) if they had not been
balanced.

Contents of A and B on Exit
-------- -- - --- - -- ----

If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or
both), then on exit the arrays A and B will contain the real Schur
form[*] of the "balanced" versions of A and B.  If no eigenvectors
are computed, then only the diagonal blocks will be correct.

[*] See DHGEQZ, DGEGS, or read the book "Matrix Computations",
    by Golub & van Loan, pub. by Johns Hopkins U. Press.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI2,mI2,nI3,mI3
# matrix A
@ARG I2,O0
@ARG lI2,lO0
# matrix B
@ARG I3,O1
@ARG lI3,lO1
# vectors ALPHAR, ALPHAI, and BETA
@ARG O2
@ARG O3
@ARG O4
# matrix VL
@ARG O5
@ARG lO5
# matrix VR
@ARG O6
@ARG lO6
@ARG ?
@ARG ?
@ARG O7
@CODE
extern void dgegv(char *jobvl, char *jobvr, int *n, double *a, int *lda,
                  double *b, int *ldb, double *alphar, double *alphai,
                  double *beta, double *vl, int *ldvl, double *vr,
                  int *ldvr, double *work, int *lwork, int *info);

int lda, ldb, ldvl = 1, ldvr = 1, lwork, nb, scratch;
/*
int one = 1;
int minusone = -1;
*/
double *work;

/*
extern int ilaenv();
*/

if (*@nI2@ != *@mI2@ || *@mI2@ != *@nI3@ || *@nI3@ != *@mI3@) 
   return NS_PROT_DIM_MISMATCH;

if (*@I0@ == 'n' || *@I0@ == 'N')  
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')  
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')  
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

lda = ldb = *@nI2@ > 1 ? *@nI2@ : 1;

if (*@I0@ == 'V')
   if (*@nI2@ > ldvl) ldvl = *@nI2@;

if (*@I1@ == 'V')
   if (*@nI2@ > ldvr) ldvr = *@nI2@;

/*
nb1 = ilaenv( &one, "dgeqrf", " ", *@nI2@, *@nI2@, &minusone, &minusone );
nb2 = ilaenv( &one, "dormqr", " ", *@nI2@, *@nI2@, *@nI2@, &minusone );
nb3 = ilaenv( &one, "dorgqr", " ", *@nI2@, *@nI2@, *@nI2@, &minusone );
nb = ( nb1 > nb2 ) ? nb1 : nb2;
nb = ( nb > nb3 ) ? nb : nb3;
*/
nb = 64;
scratch = ((6 * *@nI2@) > (*@nI2@ * (nb+1))) ? (6 * *@nI2@) : (*@nI2@ * (nb+1));
lwork = ( (2 * *@nI2@ + scratch) > 1 ) ? (2 * *@nI2@ + scratch) : 1;

work = (double *) malloc(sizeof(double) * lwork);

@O2@ = (double *) malloc(sizeof(double) * *@nI2@);
@O3@ = (double *) malloc(sizeof(double) * *@nI2@);
@O4@ = (double *) malloc(sizeof(double) * *@nI2@);
*@mO2@ = *@nI2@;
*@mO3@ = *@nI2@;
*@mO4@ = *@nI2@;

if (*@I0@ == 'V') {
   @O5@ = (double *) malloc(sizeof(double) * ldvl * *@nI2@);
   *@mO5@ = ldvl;
   *@nO5@ = *@nI2@;
} else {
   @O5@ = (double *) malloc(sizeof(double));
   *@mO5@ = ldvl;
   *@nO5@ = 1;
}

if (*@I1@ == 'V') {
   @O6@ = (double *) malloc(sizeof(double) * ldvr * *@nI2@);
   *@mO6@ = ldvr;
   *@nO6@ = *@nI2@;
} else {
   @O6@ = (double *) malloc(sizeof(double));
   *@mO6@ = ldvr;
   *@nO6@ = 1;
}

@O7@ = (int *) malloc(sizeof(int));

dgegv(@I0@, @I1@, @nI2@, @I2@, &lda, @I3@, &ldb, @O2@, @O3@,
      @O4@, @O5@, &ldvl, @O6@, &ldvr, work, &lwork, @O7@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

@O1@ = @I3@;
*@mO1@ = *@mI3@;
*@nO1@ = *@nI3@;
@END_CODE

#
# DGGEV
#
@PROBLEM dggev
@FUNCTION dggev
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B)
the generalized eigenvalues, and optionally, the left and/or right
generalized eigenvectors.

A generalized eigenvalue for a pair of matrices (A,B) is a scalar
lambda or a ratio alpha/beta = lambda, such that A - lambda*B is
singular. It is usually represented as the pair (alpha,beta), as
there is a reasonable interpretation for beta=0, and even for both
being zero.

The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
of (A,B) satisfies

                 A * v(j) = lambda(j) * B * v(j).

The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
of (A,B) satisfies

                 u(j)**H * A  = lambda(j) * u(j)**H * B .

where u(j)**H is the conjugate-transpose of u(j).
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR jobvl
JOBVL   (input) CHARACTER*1
        = 'N':  do not compute the left generalized eigenvectors;
        = 'V':  compute the left generalized eigenvectors.
@OBJECT SCALAR CHAR jobvr
JOBVR   (input) CHARACTER*1
        = 'N':  do not compute the right generalized eigenvectors;
        = 'V':  compute the right generalized eigenvectors.
@OBJECT MATRIX D a
A       (input) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the first of the pair of matrices whose
        generalized eigenvalues and (optionally) generalized
        eigenvectors are to be computed.
@OBJECT MATRIX D b
B       (input) DOUBLE PRECISION array, dimension (LDB, N)
        On entry, the second of the pair of matrices whose
        generalized eigenvalues and (optionally) generalized
        eigenvectors are to be computed.
@OUTPUT 6
@OBJECT VECTOR D alphar
ALPHAR  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D alphai
ALPHAI  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D beta
BETA    (output) DOUBLE PRECISION array, dimension (N)
        On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will
        be the generalized eigenvalues.  If ALPHAI(j) is zero, then
        the j-th eigenvalue is real; if positive, then the j-th and
        (j+1)-st eigenvalues are a complex conjugate pair, with
        ALPHAI(j+1) negative.

        Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)
        may easily over- or underflow, and BETA(j) may even be zero.
        Thus, the user should avoid naively computing the ratio
        alpha/beta.  However, ALPHAR and ALPHAI will be always less
        than and usually comparable with norm(A) in magnitude, and
        BETA always less than and usually comparable with norm(B).
@OBJECT MATRIX D vl
VL      (output) DOUBLE PRECISION array, dimension (LDVL,N)
        If JOBVL = 'V', the left generalized eigenvectors.  (See
        "Purpose", above.)  Real eigenvectors take one column,
        complex take two columns, the first for the real part and
        the second for the imaginary part.  Complex eigenvectors
        correspond to an eigenvalue with positive imaginary part.
        Each eigenvector will be scaled so the largest component
        will have abs(real part) + abs(imag. part) = 1, *except*
        that for eigenvalues with alpha=beta=0, a zero vector will
        be returned as the corresponding eigenvector.
        Not referenced if JOBVL = 'N'.
@OBJECT MATRIX D vr
VR      (output) DOUBLE PRECISION array, dimension (LDVR,N)
        If JOBVR = 'V', the right generalized eigenvectors.  (See
        "Purpose", above.)  Real eigenvectors take one column,
        complex take two columns, the first for the real part and
        the second for the imaginary part.  Complex eigenvectors
        correspond to an eigenvalue with positive imaginary part.
        Each eigenvector will be scaled so the largest component
        will have abs(real part) + abs(imag. part) = 1, *except*
        that for eigenvalues with alpha=beta=0, a zero vector will
        be returned as the corresponding eigenvector.
        Not referenced if JOBVR = 'N'.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        = 1,...,N:
              The QZ iteration failed.  No eigenvectors have been
              calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)
              should be correct for j=INFO+1,...,N.
        > N:  =N+1: other than QZ iteration failed in DHGEQZ.
              =N+2: error return from DTGEVC.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI2,mI2,nI3,mI3
# matrix A
@ARG I2
@ARG lI2
# matrix B
@ARG I3
@ARG lI3
# vectors ALPHAR, ALPHAI, and BETA
@ARG O0
@ARG O1
@ARG O2
# matrix VL
@ARG O3
@ARG lO3
# matrix VR
@ARG O4
@ARG lO4
@ARG ?
@ARG ?
@ARG O5
@CODE
extern void dggev(char *jobvl, char *jobvr, int *n, double *a, int *lda,
                  double *b, int *ldb, double *alphar, double *alphai,
                  double *beta, double *vl, int *ldvl, double *vr, 
                  int *ldvr, double *work, int *lwork, int *info);

int lda, ldb, ldvl = 1, ldvr = 1, lwork;
double *work;

if (*@nI2@ != *@mI2@ || *@mI2@ != *@nI3@ || *@nI3@ != *@mI3@) 
   return NS_PROT_DIM_MISMATCH;

if (*@I0@ == 'n' || *@I0@ == 'N')  
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')  
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')  
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

lda = ldb = *@nI2@ > 1 ? *@nI2@ : 1;

if (*@I0@ == 'V')
   if (*@nI2@ > ldvl) ldvl = *@nI2@;

if (*@I1@ == 'V')
   if (*@nI2@ > ldvr) ldvr = *@nI2@;

lwork = ( (8 * *@nI2@) > 1 ) ? (8 * *@nI2@) : 1;

work = (double *) malloc(sizeof(double) * lwork);

@O0@ = (double *) malloc(sizeof(double) * *@nI2@);
@O1@ = (double *) malloc(sizeof(double) * *@nI2@);
@O2@ = (double *) malloc(sizeof(double) * *@nI2@);
*@mO0@ = *@nI2@;
*@mO1@ = *@nI2@;
*@mO2@ = *@nI2@;

if (*@I0@ == 'V') {
   @O3@ = (double *) malloc(sizeof(double) * ldvl * *@nI2@);
   *@mO3@ = ldvl;
   *@nO3@ = *@nI2@;
} else {
   @O3@ = (double *) malloc(sizeof(double));
   *@mO3@ = ldvl;
   *@nO3@ = 1;
}

if (*@I1@ == 'V') {
   @O4@ = (double *) malloc(sizeof(double) * ldvr * *@nI2@);
   *@mO4@ = ldvr;
   *@nO4@ = *@nI2@;
} else {
   @O4@ = (double *) malloc(sizeof(double));
   *@mO4@ = ldvr;
   *@nO4@ = 1;
}

@O5@ = (int *) malloc(sizeof(int));

dggev(@I0@, @I1@, @nI2@, @I2@, &lda, @I3@, &ldb, @O0@, @O1@,
      @O2@, @O3@, &ldvl, @O4@, &ldvr, work, &lwork, @O5@);


@END_CODE


#
# DGEGS
#
@PROBLEM dgegs
@FUNCTION dgegs
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DGEGS computes for a pair of N-by-N real nonsymmetric matrices A, B:
the generalized eigenvalues (alphar +/- alphai*i, beta), the real
Schur form (A, B), and optionally left and/or right Schur vectors
(VSL and VSR).

(If only the generalized eigenvalues are needed, use the driver DGEGV
instead.)

A generalized eigenvalue for a pair of matrices (A,B) is, roughly
speaking, a scalar w or a ratio  alpha/beta = w, such that  A - w*B
is singular.  It is usually represented as the pair (alpha,beta),
as there is a reasonable interpretation for beta=0, and even for
both being zero.  A good beginning reference is the book, "Matrix
Computations", by G. Golub & C. van Loan (Johns Hopkins U. Press)

The (generalized) Schur form of a pair of matrices is the result of
multiplying both matrices on the left by one orthogonal matrix and
both on the right by another orthogonal matrix, these two orthogonal
matrices being chosen so as to bring the pair of matrices into
(real) Schur form.

A pair of matrices A, B is in generalized real Schur form if B is
upper triangular with non-negative diagonal and A is block upper
triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
to real generalized eigenvalues, while 2-by-2 blocks of A will be
"standardized" by making the corresponding elements of B have the
form:
        [  a  0  ]
        [  0  b  ]

and the pair of corresponding 2-by-2 blocks in A and B will
have a complex conjugate pair of generalized eigenvalues.

The left and right Schur vectors are the columns of VSL and VSR,
respectively, where VSL and VSR are the orthogonal matrices
which reduce A and B to Schur form:

Schur form of (A,B) = ( (VSL)**T A (VSR), (VSL)**T B (VSR) )
http://www.netlib.org/lapack/
@INPUT 4
@OBJECT SCALAR CHAR jobvsl
JOBVSL  (input) CHARACTER*1
        = 'N':  do not compute the left Schur vectors;
        = 'V':  compute the left Schur vectors.
@OBJECT SCALAR CHAR jobvsr
JOBVSR  (input) CHARACTER*1
        = 'N':  do not compute the right Schur vectors;
        = 'V':  compute the right Schur vectors.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the first of the pair of matrices whose generalized
        eigenvalues and (optionally) Schur vectors are to be
        computed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On entry, the second of the pair of matrices whose
        generalized eigenvalues and (optionally) Schur vectors are
        to be computed.
@OUTPUT 8
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, the generalized Schur form of A.
        Note: to avoid overflow, the Frobenius norm of the matrix
        A should be less than the overflow threshold.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On exit, the generalized Schur form of B.
        Note: to avoid overflow, the Frobenius norm of the matrix
        B should be less than the overflow threshold.
@OBJECT VECTOR D alphar
ALPHAR  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D alphai
ALPHAI  (output) DOUBLE PRECISION array, dimension (N)
@OBJECT VECTOR D beta
BETA    (output) DOUBLE PRECISION array, dimension (N)
        On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will
        be the generalized eigenvalues.  ALPHAR(j) + ALPHAI(j)*i,
        j=1,...,N  and  BETA(j),j=1,...,N  are the diagonals of the
        complex Schur form (A,B) that would result if the 2-by-2
        diagonal blocks of the real Schur form of (A,B) were further
        reduced to triangular form using 2-by-2 complex unitary
        transformations.  If ALPHAI(j) is zero, then the j-th
        eigenvalue is real; if positive, then the j-th and (j+1)-st
        eigenvalues are a complex conjugate pair, with ALPHAI(j+1)
        negative.

        Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)
        may easily over- or underflow, and BETA(j) may even be zero.
        Thus, the user should avoid naively computing the ratio
        alpha/beta.  However, ALPHAR and ALPHAI will be always less
        than and usually comparable with norm(A) in magnitude, and
        BETA always less than and usually comparable with norm(B).
@OBJECT MATRIX D vsl
VSL     (output) DOUBLE PRECISION array, dimension (LDVSL,N)
        If JOBVSL = 'V', VSL will contain the left Schur vectors.
        (See "Purpose", above.)
        Not referenced if JOBVSL = 'N'.
@OBJECT MATRIX D vsr
VSR     (output) DOUBLE PRECISION array, dimension (LDVSR,N)
        If JOBVSR = 'V', VSR will contain the right Schur vectors.
        (See "Purpose", above.)
        Not referenced if JOBVSR = 'N'.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value.
        = 1,...,N:
              The QZ iteration failed.  (A,B) are not in Schur
              form, but ALPHAR(j), ALPHAI(j), and BETA(j) should
              be correct for j=INFO+1,...,N.
        > N:  errors that usually indicate LAPACK problems:
              =N+1: error return from DGGBAL
              =N+2: error return from DGEQRF
              =N+3: error return from DORMQR
              =N+4: error return from DORGQR
              =N+5: error return from DGGHRD
              =N+6: error return from DHGEQZ (other than failed
                                              iteration)
              =N+7: error return from DGGBAK (computing VSL)
              =N+8: error return from DGGBAK (computing VSR)
              =N+9: error return from DLASCL (various places)
@COMPLEXITY 2,3
@CALLINGSEQUENCE
# jobvsl
@ARG I0
# jobvsr
@ARG I1
# N
@ARG nI2,nI3,mI2,mI3
# matrix A, (LDA, N)
@ARG I2,O0
# lda
@ARG lI2,lO0
# matrix B, (LDB, N)
@ARG I3,O1
# ldb
@ARG lI3,lO1
# alphar
@ARG O2
# alphai
@ARG O3
# beta
@ARG O4
# matrix VSL, (LDVSL, N)
@ARG O5
# ldvsl
@ARG lO5
# matrix VSR, (LDVSR, N)
@ARG O6
# ldvsr
@ARG lO6
# work
@ARG ?
# lwork
@ARG ?
# info
@ARG O7
@CODE
extern void dgegs(char *jobvsl, char *jobvsr, int *n, double *a,
                  int *lda, double *b, int *ldb, double *alphar,
                  double *alphai, double *beta, double *vsl, int *ldvsl,
                  double *vsr, int *ldvsr, double *work, int *lwork,
                  int *info);

int lda, ldb, ldvsl = 1, ldvsr = 1, lwork, nb, scratch;
double *work;
/*
int one = 1;
int minusone = -1;
*/

/*
extern int ilaenv();
*/

if (*@nI2@ != *@mI2@ || *@mI2@ != *@nI3@ || *@nI3@ != *@mI3@) 
   return NS_PROT_DIM_MISMATCH;

if (*@I0@ == 'n' || *@I0@ == 'N')  
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')  
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')  
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

lda = ldb = *@nI2@ > 1 ? *@nI2@ : 1;

if (*@I0@ == 'V') 
   if (*@nI2@ > ldvsl) ldvsl = *@nI2@;

if (*@I1@ == 'V')  
   if (*@nI2@ > ldvsr) ldvsr = *@nI2@;

/*
nb1 = ilaenv( &one, "dgeqrf", " ", *@nI2@, *@nI2@, &minusone, &minusone );
nb2 = ilaenv( &one, "dormqr", " ", *@nI2@, *@nI2@, *@nI2@, &minusone );
nb3 = ilaenv( &one, "dorgqr", " ", *@nI2@, *@nI2@, *@nI2@, &minusone );
nb = ( nb1 > nb2 ) ? nb1 : nb2;
nb = ( nb > nb3 ) ? nb : nb3;
*/
nb = 64;
scratch = *@nI2@ * (nb+1);
lwork = ( (2 * *@nI2@ + scratch) > 1 ) ? (2 * *@nI2@ + scratch) : 1;

work = (double *) malloc(sizeof(double) * lwork);

@O2@ = (double *) malloc(sizeof(double) * *@nI2@);
@O3@ = (double *) malloc(sizeof(double) * *@nI2@);
@O4@ = (double *) malloc(sizeof(double) * *@nI2@);
*@mO2@ = *@nI2@;
*@mO3@ = *@nI2@;
*@mO4@ = *@nI2@;

@O5@ = (double *) malloc(sizeof(double) * ldvsl * *@nI2@);
*@mO5@ = ldvsl;
*@nO5@ = *@nI2@;

@O6@ = (double *) malloc(sizeof(double) * ldvsr * *@nI2@);
*@mO6@ = ldvsr;
*@nO6@ = *@nI2@;

@O7@ = (int *) malloc(sizeof(int));

dgegs(@I0@, @I1@, @nI2@, @I2@, &lda, @I3@, &ldb, @O2@, @O3@,
      @O4@, @O5@, &ldvsl, @O6@, &ldvsr, work, &lwork, @O7@);

@O0@ = @I2@;
*@mO0@ = *@mI2@;
*@nO0@ = *@nI2@;

@O1@ = @I3@;
*@mO1@ = *@mI3@;
*@nO1@ = *@nI3@;
@END_CODE


#
# DSBGV
#
@PROBLEM dsbgv
@FUNCTION dsbgv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DSBGV computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite banded eigenproblem, of
the form A*x=(lambda)*B*x. Here A and B are assumed to be symmetric
and banded, and B is also positive definite.
http://www.netlib.org/lapack/
@INPUT 6
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangles of A and B are stored;
        = 'L':  Lower triangles of A and B are stored.
@OBJECT SCALAR I ka
KA      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'. KA >= 0.
@OBJECT SCALAR I kb
KB      (input) INTEGER
        The number of superdiagonals of the matrix B if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'. KB >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first ka+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+ka).
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix B, stored in the first kb+1 rows of the array.  The
        j-th column of B is stored in the j-th column of the array BB
        as follows:
        if UPLO = 'U', BB(kb+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;
        if UPLO = 'L', BB(1+i-j,j)    = B(i,j) for j<=i<=min(n,j+kb).
@OUTPUT 5
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first ka+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+ka).
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On exit, the factor S from the split Cholesky factorization
        B = S**T*S, as returned by DPBSTF.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of
        eigenvectors, with the i-th column of Z holding the
        eigenvector associated with W(i). The eigenvectors are
        normalized so that Z**T*B*Z = I.
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, and i is:
           <= N:  the algorithm failed to converge:
                  i off-diagonal elements of an intermediate
                  tridiagonal form did not converge to zero;
           > N:   if INFO = N + i, for 1 <= i <= N, then DPBSTF
                  returned INFO = i: B is not positive definite.
                  The factorization of B could not be completed and
                  no eigenvalues or eigenvectors were computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI4,nI5
@ARG I2
@ARG I3
@ARG I4,O0
@ARG lI4,lO0
@ARG I5,O1
@ARG lI5,lO1
@ARG O2
@ARG O3
@ARG lO3
@ARG ?
@ARG O4
@COMP mI4=op(+,array(I2,0),1)
@COMP mI5=op(+,array(I3,0),1)
@CODE
extern void dsbgv(char *jobz, char *uplo, int *n, int *ka, int *kb,
                  double *ab, int *ldab, double *bb, int *ldbb,
                  double *w, double *z, int *ldz, double *work, int *info);

int ldab, ldbb, ldz, lwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')  
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')  
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')  
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldab = (*@I2@ > 1) ? *@I2@ : 1;
ldab +=1;
ldbb = (*@I3@ > 1) ? *@I3@ : 1;
ldbb +=1;

lwork = (3 * *@nI4@ > 1) ? 3 * *@nI4@ : 1;

ldz = 1;
if (*@I0@ == 'V') 
   ldz = *@nI4@ > 1 ? *@nI4@ : 1;

@O2@ = (double *) malloc(sizeof(double) * *@nI4@);
@O3@ = (double *) malloc(sizeof(double) * *@nI4@ * ldz);
work = (double *) malloc(sizeof(double) * *@nI4@ * 3);
@O4@ = (int *) malloc(sizeof(int));

dsbgv(@I0@, @I1@, @nI4@, @I2@, @I3@, @I4@, &ldab,
      @I5@, &ldbb, @O2@, @O3@, &ldz, work, @O4@);

if (*@O4@ != 0) 
   printf(" dsbgv info = %d \n",*@O4@);

@O0@ = @I4@;
*@mO0@ = *@mI4@;
*@nO0@ = *@nI4@;

@O1@ = @I5@;
*@mO1@ = *@mI5@;
*@nO1@ = *@nI5@;

*@mO2@ = *@nI4@;

*@mO3@ = ldz;
*@nO3@ = *@nI4@;

if (*@O4@ != 0) 
   printf(" dsbgv info = %d \n",*@O4@);
@END_CODE

#
# DSBGVD
#
@PROBLEM dsbgvd
@FUNCTION dsbgvd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/DivideandConquer/Gen_Eig_and_Singular/
@DESCRIPTION
DSBGVD computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite banded eigenproblem, of the
form A*x=(lambda)*B*x.  Here A and B are assumed to be symmetric and
banded, and B is also positive definite.  If eigenvectors are
desired, it uses a divide and conquer algorithm.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 6
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangles of A and B are stored;
        = 'L':  Lower triangles of A and B are stored.
@OBJECT SCALAR I ka
KA      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'. KA >= 0.
@OBJECT SCALAR I kb
KB      (input) INTEGER
        The number of superdiagonals of the matrix B if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'. KB >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first ka+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+ka).

        On exit, the contents of AB are destroyed.
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix B, stored in the first kb+1 rows of the array.  The
        j-th column of B is stored in the j-th column of the array BB
        as follows:
        if UPLO = 'U', BB(kb+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;
        if UPLO = 'L', BB(1+i-j,j)    = B(i,j) for j<=i<=min(n,j+kb).
@OUTPUT 5
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On exit, the contents of AB are destroyed.
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On exit, the factor S from the split Cholesky factorization
        B = S**T*S, as returned by DPBSTF.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of
        eigenvectors, with the i-th column of Z holding the
        eigenvector associated with W(i). The eigenvectors are
        normalized so that Z**T*B*Z = I.
        If JOBZ = 'N', then Z is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, and i is:
           <= N:  the algorithm failed to converge:
                  i off-diagonal elements of an intermediate
                  tridiagonal form did not converge to zero;
           > N:   if INFO = N + i, for 1 <= i <= N, then DPBSTF
                  returned INFO = i: B is not positive definite.
                  The factorization of B could not be completed and
                  no eigenvalues or eigenvectors were computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG nI4,nI5
@ARG I2
@ARG I3
@ARG I4,O0
@ARG lI4,lO0
@ARG I5,O1
@ARG lI5,lO1
@ARG O2
@ARG O3
@ARG lO3
@ARG ?
@ARG ?
@ARG ?
@ARG ?
@ARG O4
@COMP mI4=op(+,array(I2,0),1)
@COMP mI5=op(+,array(I3,0),1)
@CODE
extern void dsbgvd(char *jobz, char *uplo, int *n, int *ka, int *kb,
                   double *ab, int *ldab, double *bb, int *ldbb,
                   double *w, double *z, int *ldz, double *work,
                   int *lwork, int *iwork, int *liwork, int *info);

int ldab, ldbb, ldz, lwork, liwork;
double *work;
int *iwork;

if (*@I0@ == 'n' || *@I0@ == 'N')  
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')  
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'u' || *@I1@ == 'U')  
   *@I1@ = 'U';
else if (*@I1@ == 'l' || *@I1@ == 'L')  
   *@I1@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldab = *@I2@ + 1;
ldbb = *@I3@ + 1;

ldz = 1;
if (*@I0@ == 'V') 
   ldz = *@nI4@ > 1 ? *@nI4@ : 1;

@O2@ = (double *) malloc(sizeof(double) * *@nI4@);

*@mO3@ = ldz;
if (*@I0@ == 'N') {
   @O3@ = (double *) malloc(sizeof(double));
   *@nO3@ = 1;
   lwork = ( ( 3 * *@nI4@ ) > 1 ) ? (3* *@nI4@) : 1;
   liwork = 1;
} else {
   @O3@ = (double *) malloc(sizeof(double) * *@nI4@ * ldz);
   *@nO3@ = *@nI4@;
   lwork = 1 + 5 * *@nI4@ + 2 * *@nI4@ * *@nI4@;
   liwork = ( (3 + 5 * *@nI4@) > 1 ) ? (3 + 5 * *@nI4@) : 1;
}

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);
@O4@ = (int *) malloc(sizeof(int));

dsbgvd(@I0@, @I1@, @nI4@, @I2@, @I3@, @I4@, &ldab,
      @I5@, &ldbb, @O2@, @O3@, &ldz, work, &lwork,
      iwork, &liwork, @O4@);

@O0@ = @I4@;
*@mO0@ = *@mI4@;
*@nO0@ = *@nI4@;

@O1@ = @I5@;
*@mO1@ = *@mI5@;
*@nO1@ = *@nI5@;

*@mO2@ = *@nI4@;
@END_CODE

#
# DSBGVX
#
@PROBLEM dsbgvx
@FUNCTION dsbgvx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Expert/Eig_and_Singular/
@DESCRIPTION
DSBGVX computes selected eigenvalues, and optionally, eigenvectors
of a real generalized symmetric-definite banded eigenproblem, of
the form A*x=(lambda)*B*x.  Here A and B are assumed to be symmetric
and banded, and B is also positive definite.  Eigenvalues and
eigenvectors can be selected by specifying either all eigenvalues,
a range of values or a range of indices for the desired eigenvalues.
http://www.netlib.org/lapack/
@INPUT 12
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT SCALAR I ka
KA      (input) INTEGER
        The number of superdiagonals of the matrix A if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KA >= 0.
@OBJECT SCALAR I kb
KB      (input) INTEGER
        The number of superdiagonals of the matrix B if UPLO = 'U',
        or the number of subdiagonals if UPLO = 'L'.  KB >= 0.
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).

        On exit, AB is overwritten by values generated during the
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix B, stored in the first kb+1 rows of the array.  The
        j-th column of B is stored in the j-th column of the array BB
        as follows:
        if UPLO = 'U', BB(ka+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;
        if UPLO = 'L', BB(1+i-j,j)    = B(i,j) for j<=i<=min(n,j+kb).

        On exit, the factor S from the split Cholesky factorization
        B = S**T*S, as returned by DPBSTF.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        Eigenvalues will be computed most accurately when ABSTOL is
        set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        If this routine returns with INFO>0, indicating that some
        eigenvectors did not converge, try setting ABSTOL to
        2*DLAMCH('S').

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.
@OUTPUT 8
@OBJECT MATRIX D ab
AB      (input/output) DOUBLE PRECISION array, dimension (LDAB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix A, stored in the first KD+1 rows of the array.  The
        j-th column of A is stored in the j-th column of the array AB
        as follows:
        if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
        if UPLO = 'L', AB(1+i-j,j)    = A(i,j) for j<=i<=min(n,j+kd).

        On exit, AB is overwritten by values generated during the
        reduction to tridiagonal form.  If UPLO = 'U', the first
        superdiagonal and the diagonal of the tridiagonal matrix T
        are returned in rows KD and KD+1 of AB, and if UPLO = 'L',
        the diagonal and first subdiagonal of T are returned in the
        first two rows of AB.
@OBJECT MATRIX D bb
BB      (input/output) DOUBLE PRECISION array, dimension (LDBB, N)
        On entry, the upper or lower triangle of the symmetric band
        matrix B, stored in the first kb+1 rows of the array.  The
        j-th column of B is stored in the j-th column of the array BB
        as follows:
        if UPLO = 'U', BB(ka+1+i-j,j) = B(i,j) for max(1,j-kb)<=i<=j;
        if UPLO = 'L', BB(1+i-j,j)    = B(i,j) for j<=i<=min(n,j+kb).

        On exit, the factor S from the split Cholesky factorization
        B = S**T*S, as returned by DPBSTF.
@OBJECT MATRIX D q
Q       (output) DOUBLE PRECISION array, dimension (LDQ, N)
        If JOBZ = 'V', the n-by-n matrix used in the reduction of
        A*x = (lambda)*B*x to standard form, i.e. C*x = (lambda)*x,
        and consequently C to tridiagonal form.
        If JOBZ = 'N', the array Q is not referenced.
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, N)
        If JOBZ = 'V', then if INFO = 0, Z contains the matrix Z of
        eigenvectors, with the i-th column of Z holding the
        eigenvector associated with W(i).  The eigenvectors are
        normalized so Z**T*B*Z = I.
        If JOBZ = 'N', then Z is not referenced.
@OBJECT VECTOR I ifail
IFAIL   (output) INTEGER array, dimension (N)
        If JOBZ = 'V', then if INFO = 0, the first M elements of
        IFAIL are zero.  If INFO > 0, then IFAIL contains the
        indices of the eigenvectors that failed to converge.
        If JOBZ = 'N', then IFAIL is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  if INFO = i, then i eigenvectors failed to converge.
              Their indices are stored in array IFAIL.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI5,nI6
@ARG I3
@ARG I4
@ARG I5,O0
@ARG lI5,lO0
@ARG I6,O1
@ARG lI6,lO1
@ARG O2
@ARG lO2
@ARG I7
@ARG I8
@ARG I9
@ARG I10
@ARG I11
@ARG O3
@ARG O4
@ARG O5
@ARG lO5
@ARG ?
@ARG ?
@ARG O6
@ARG O7
@COMP mI5=op(+,array(I3,0),1)
@COMP mI6=op(+,array(I4,0),1)
@CODE
extern void dsbgvx(char *jobz, char *range, char *uplo, int *n, int *ka,
                   int *kb, double *ab, int *ldab, double *bb, int *ldbb,
                   double *q, int *ldq, double *vl, double *vu, int *il,
                   int *iu, double *abstol, int *m, double *w, double *z,
                   int *ldz, double *work, int *iwork, int *ifail, int *info);

int ldab, ldbb, ldq, ldz, liwork, lwork, *iwork;
double *work;

if (*@I0@ == 'n' || *@I0@ == 'N')
   *@I0@ = 'N';
else if (*@I0@ == 'v' || *@I0@ == 'V')
   *@I0@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'a' || *@I1@ == 'A')
   *@I1@ = 'A';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else if (*@I1@ == 'i' || *@I1@ == 'I')
   *@I1@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

ldab = (*@I3@ > 1) ? *@I3@ : 1;
ldab +=1;
ldbb = (*@I4@ > 1) ? *@I4@ : 1;
ldbb +=1;
ldq = (*@nI5@ > 1) ? *@nI5@ : 1;
ldz = (*@nI5@ > 1) ? *@nI5@ : 1;

liwork = (5 * *@nI5@ > 1) ? 5 * *@nI5@ : 1;
lwork = (7 * *@nI5@ > 1) ? 7 * *@nI5@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O2@ = (double *) malloc(sizeof(double) * ldq * *@nI5@);
@O3@ = (int *) malloc(sizeof(int));
@O4@ = (double *) malloc(sizeof(double) * *@nI5@);
@O5@ = (double *) malloc(sizeof(double) * ldz * *@nI5@);
@O6@ = (int *) malloc(sizeof(int) * *@nI5@);
@O7@ = (int *) malloc(sizeof(int));

dsbgvx(@I0@, @I1@, @I2@, @nI5@, @I3@, @I4@, @I5@, &ldab,
       @I6@, &ldbb, @O2@, &ldq,
       @I7@, @I8@, @I9@, @I10@, @I11@, @O3@, @O4@, @O5@, &ldz,
       work, iwork, @O6@, @O7@);

@O0@ = @I5@;
*@mO0@ = *@mI5@;
*@nO0@ = *@nI5@;

@O1@ = @I6@;
*@mO1@ = *@mI6@;
*@nO1@ = *@nI6@;

*@mO2@ = *@nI5@;
*@nO2@ = *@nI5@;

*@mO4@ = *@nI5@;

*@mO5@ = *@nI5@;
*@nO5@ = *@nI5@;

*@mO6@ = *@nI5@;
@END_CODE

#
# DSYGV
#
@PROBLEM dsygv
@FUNCTION dsygv
#@FUNCTION ilaenv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DSYGV computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A*x=(lambda)*B*x,  A*Bx=(lambda)*x,  or B*A*x=(lambda)*x.
Here A and B are assumed to be symmetric and B is also
positive definite.
http://www.netlib.org/lapack/
@INPUT 5
@OBJECT SCALAR I itype
ITYPE   (input) INTEGER
        Specifies the problem type to be solved:
        = 1:  A*x = (lambda)*B*x
        = 2:  A*B*x = (lambda)*x
        = 3:  B*A*x = (lambda)*x
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangles of A and B are stored;
        = 'L':  Lower triangles of A and B are stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On entry, the symmetric positive definite matrix B.
        If UPLO = 'U', the leading N-by-N upper triangular part of B
        contains the upper triangular part of the matrix B.
        If UPLO = 'L', the leading N-by-N lower triangular part of B
        contains the lower triangular part of the matrix B.
@OUTPUT 4
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, if JOBZ = 'V', then if INFO = 0, A contains the
        matrix Z of eigenvectors.  The eigenvectors are normalized
        as follows:
        if ITYPE = 1 or 2, Z**T*B*Z = I;
        if ITYPE = 3, Z**T*inv(B)*Z = I.
        If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
        or the lower triangle (if UPLO='L') of A, including the
        diagonal, is destroyed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On exit, if INFO <= N, the part of B containing the matrix is
        overwritten by the triangular factor U or L from the Cholesky
        factorization B = U**T*U or B = L*L**T.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  DPOTRF or DSYEV returned an error code:
           <= N:  if INFO = i, DSYEV failed to converge;
                  i off-diagonal elements of an intermediate
                  tridiagonal form did not converge to zero;
        > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                  minor of order i of B is not positive definite.
                  The factorization of B could not be completed and
                  no eigenvalues or eigenvectors were computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI3,mI3,nI4,mI4
@ARG I3,O0
@ARG lI3,lO0
@ARG I4,O1
@ARG lI4,lO1
@ARG O2
@ARG ?
@ARG ?
@ARG O3
@CODE
extern void dsygv(int *itype, char *jobz, char *uplo, int *n, double *a,
                  int *lda, double *b, int *ldb, double *w, double *work,
                  int *lwork, int *info);

int lda, ldb, nb;
/*
int one = 1;
int minusone = -1;
*/
int lwork;
double *work;

/*
extern int ilaenv();
*/

if (*@nI3@ != *@mI3@ || *@mI3@ != *@nI4@ || *@nI4@ != *@mI4@) 
   return NS_PROT_DIM_MISMATCH;

if (*@I0@ != 1 && *@I0@ != 2 && *@I0@ != 3)
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')  
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')  
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')  
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')  
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

lda = ldb = (*@nI3@ > 1) ? *@nI3@ : 1;

/*
nb = ilaenv( &one, "dsytrd", *@I2@, *@nI3@, &minusone, &minusone, &minusone );
*/
nb = 64;
lwork = ( ((nb+2)* *@nI3@) > 1 ) ? ((nb+2)* *@nI3@) : 1;
work = (double *) malloc(sizeof(double) * lwork);

@O2@ = (double *) malloc(sizeof(double) * *@nI3@);
*@mO2@ = *@nI3@;

@O3@ = (int *) malloc(sizeof(int));

dsygv(@I0@, @I1@, @I2@, @nI3@, @I3@, &lda, @I4@, &ldb, @O2@, 
      work, &lwork, @O3@);

@O0@ = @I3@;
*@mO0@ = *@mI3@;
*@nO0@ = *@nI3@;

@O1@ = @I4@;
*@mO1@ = *@mI4@;
*@nO1@ = *@nI4@;

@END_CODE

#
# DSYGVD
#
@PROBLEM dsygvd
@FUNCTION dsygvd
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Simple/Gen_Eig_and_Singular/
@DESCRIPTION
DSYGVD computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A*x=(lambda)*B*x,  A*Bx=(lambda)*x,  or B*A*x=(lambda)*x.  Here A and
B are assumed to be symmetric and B is also positive definite.
If eigenvectors are desired, it uses a divide and conquer algorithm.

The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
http://www.netlib.org/lapack/
@INPUT 5
@OBJECT SCALAR I itype
ITYPE   (input) INTEGER
        Specifies the problem type to be solved:
        = 1:  A*x = (lambda)*B*x
        = 2:  A*B*x = (lambda)*x
        = 3:  B*A*x = (lambda)*x
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangles of A and B are stored;
        = 'L':  Lower triangles of A and B are stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On entry, the symmetric positive definite matrix B.
        If UPLO = 'U', the leading N-by-N upper triangular part of B
        contains the upper triangular part of the matrix B.
        If UPLO = 'L', the leading N-by-N lower triangular part of B
        contains the lower triangular part of the matrix B.
@OUTPUT 4
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On exit, if JOBZ = 'V', then if INFO = 0, A contains the
        matrix Z of eigenvectors.  The eigenvectors are normalized
        as follows:
        if ITYPE = 1 or 2, Z**T*B*Z = I;
        if ITYPE = 3, Z**T*inv(B)*Z = I.
        If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
        or the lower triangle (if UPLO='L') of A, including the
        diagonal, is destroyed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
        On exit, if INFO <= N, the part of B containing the matrix is
        overwritten by the triangular factor U or L from the Cholesky
        factorization B = U**T*U or B = L*L**T.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        If INFO = 0, the eigenvalues in ascending order.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  DPOTRF or DSYEV returned an error code:
           <= N:  if INFO = i, DSYEV failed to converge;
                  i off-diagonal elements of an intermediate
                  tridiagonal form did not converge to zero;
        > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                  minor of order i of B is not positive definite.
                  The factorization of B could not be completed and
                  no eigenvalues or eigenvectors were computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG nI3,mI3,nI4,mI4
@ARG I3,O0
@ARG lI3,lO0
@ARG I4,O1
@ARG lI4,lO1
@ARG O2
@ARG ?
@ARG ?
@ARG O3
@CODE
extern void dsygvd(int *itype, char *jobz, char *uplo, int *n, double *a,
                   int *lda, double *b, int *ldb, double *w, double *work,
                   int *lwork, int *iwork, int *liwork, int *info);

int lda, ldb;
int lwork, liwork;
double *work;
int *iwork;

if (*@nI3@ != *@mI3@ || *@mI3@ != *@nI4@ || *@nI4@ != *@mI4@) 
   return NS_PROT_DIM_MISMATCH;

if (*@I0@ != 1 && *@I0@ != 2 && *@I0@ != 3)
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')  
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')  
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'u' || *@I2@ == 'U')  
   *@I2@ = 'U';
else if (*@I2@ == 'l' || *@I2@ == 'L')  
   *@I2@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

lda = ldb = (*@nI3@ > 1) ? *@nI3@ : 1;

if (*@I1@ == 'N') {
   lwork = 2 * *@nI3@ + 1;
   liwork = 1;
} else {
   lwork = 1 + 6 * *@nI3@ + 2 * *@nI3@ * *@nI3@;
   liwork = ( (3 + 5 * *@nI3@) > 1 ) ? (3 + 5 * *@nI3@) : 1;
}

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O2@ = (double *) malloc(sizeof(double) * *@nI3@);
*@mO2@ = *@nI3@;

@O3@ = (int *) malloc(sizeof(int));

dsygvd(@I0@, @I1@, @I2@, @nI3@, @I3@, &lda, @I4@, &ldb, @O2@, 
      work, &lwork, iwork, &liwork, @O3@);

@O0@ = @I3@;
*@mO0@ = *@mI3@;
*@nO0@ = *@nI3@;

@O1@ = @I4@;
*@mO1@ = *@mI4@;
*@nO1@ = *@nI4@;

@END_CODE

#
# DSYGVX
#
@PROBLEM dsygvx
@FUNCTION dsygvx
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK/Expert/Eig_and_Singular/
@DESCRIPTION
DSYGVX computes selected eigenvalues, and optionally, eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A*x=(lambda)*B*x,  A*Bx=(lambda)*x,  or B*A*x=(lambda)*x.  Here A
and B are assumed to be symmetric and B is also positive definite.
Eigenvalues and eigenvectors can be selected by specifying either a
range of values or a range of indices for the desired eigenvalues.
http://www.netlib.org/lapack/
@INPUT 11
@OBJECT SCALAR I itype
ITYPE   (input) INTEGER
        Specifies the problem type to be solved:
        = 1:  A*x = (lambda)*B*x
        = 2:  A*B*x = (lambda)*x
        = 3:  B*A*x = (lambda)*x
@OBJECT SCALAR CHAR jobz
JOBZ    (input) CHARACTER*1
        = 'N':  Compute eigenvalues only;
        = 'V':  Compute eigenvalues and eigenvectors.
@OBJECT SCALAR CHAR range
RANGE   (input) CHARACTER*1
        = 'A': all eigenvalues will be found.
        = 'V': all eigenvalues in the half-open interval (VL,VU]
               will be found.
        = 'I': the IL-th through IU-th eigenvalues will be found.
@OBJECT SCALAR CHAR uplo
UPLO    (input) CHARACTER*1
        = 'U':  Upper triangle of A is stored;
        = 'L':  Lower triangle of A is stored.
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.

        On exit, the lower triangle (if UPLO='L') or the upper
        triangle (if UPLO='U') of A, including the diagonal, is
        destroyed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix B.  If UPLO = 'U', the
        leading N-by-N upper triangular part of B contains the
        upper triangular part of the matrix B.  If UPLO = 'L',
        the leading N-by-N lower triangular part of B contains
        the lower triangular part of the matrix B.

        On exit, if INFO <= N, the part of B containing the matrix is
        overwritten by the triangular factor U or L from the Cholesky
        factorization B = U**T*U or B = L*L**T.
@OBJECT SCALAR D vl
VL      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR D vu
VU      (input) DOUBLE PRECISION
        If RANGE='V', the lower and upper bounds of the interval to
        be searched for eigenvalues. VL < VU.
        Not referenced if RANGE = 'A' or 'I'.
@OBJECT SCALAR I il
IL      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR I iu
IU      (input) INTEGER
        If RANGE='I', the indices (in ascending order) of the
        smallest and largest eigenvalues to be returned.
        1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
        Not referenced if RANGE = 'A' or 'V'.
@OBJECT SCALAR D abstol
ABSTOL  (input) DOUBLE PRECISION
        The absolute error tolerance for the eigenvalues.
        An approximate eigenvalue is accepted as converged
        when it is determined to lie in an interval [a,b]
        of width less than or equal to

                ABSTOL + EPS *   max( |a|,|b| ) ,

        where EPS is the machine precision.  If ABSTOL is less than
        or equal to zero, then  EPS*|T|  will be used in its place,
        where |T| is the 1-norm of the tridiagonal matrix obtained
        by reducing A to tridiagonal form.

        Eigenvalues will be computed most accurately when ABSTOL is
        set to twice the underflow threshold 2*DLAMCH('S'), not zero.
        If this routine returns with INFO>0, indicating that some
        eigenvectors did not converge, try setting ABSTOL to
        2*DLAMCH('S').

        See "Computing Small Singular Values of Bidiagonal Matrices
        with Guaranteed High Relative Accuracy," by Demmel and
        Kahan, LAPACK Working Note #3.
@OUTPUT 7
@OBJECT MATRIX D a
A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix A.  If UPLO = 'U', the
        leading N-by-N upper triangular part of A contains the
        upper triangular part of the matrix A.  If UPLO = 'L',
        the leading N-by-N lower triangular part of A contains
        the lower triangular part of the matrix A.

        On exit, the lower triangle (if UPLO='L') or the upper
        triangle (if UPLO='U') of A, including the diagonal, is
        destroyed.
@OBJECT MATRIX D b
B       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
        On entry, the symmetric matrix B.  If UPLO = 'U', the
        leading N-by-N upper triangular part of B contains the
        upper triangular part of the matrix B.  If UPLO = 'L',
        the leading N-by-N lower triangular part of B contains
        the lower triangular part of the matrix B.

        On exit, if INFO <= N, the part of B containing the matrix is
        overwritten by the triangular factor U or L from the Cholesky
        factorization B = U**T*U or B = L*L**T.
@OBJECT SCALAR I m
M       (output) INTEGER
        The total number of eigenvalues found.  0 <= M <= N.
        If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
@OBJECT VECTOR D w
W       (output) DOUBLE PRECISION array, dimension (N)
        On normal exit, the first M elements contain the selected
        eigenvalues in ascending order.
@OBJECT MATRIX D z
Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M))
        If JOBZ = 'N', then Z is not referenced.
        If JOBZ = 'V', then if INFO = 0, the first M columns of Z
        contain the orthonormal eigenvectors of the matrix A
        corresponding to the selected eigenvalues, with the i-th
        column of Z holding the eigenvector associated with W(i).
        The eigenvectors are normalized as follows:
        if ITYPE = 1 or 2, Z**T*B*Z = I;
        if ITYPE = 3, Z**T*inv(B)*Z = I.

        If an eigenvector fails to converge, then that column of Z
        contains the latest approximation to the eigenvector, and the
        index of the eigenvector is returned in IFAIL.
        Note: the user must ensure that at least max(1,M) columns are
        supplied in the array Z; if RANGE = 'V', the exact value of M
        is not known in advance and an upper bound must be used.
@OBJECT VECTOR I ifail
IFAIL   (output) INTEGER array, dimension (N)
        If JOBZ = 'V', then if INFO = 0, the first M elements of
        IFAIL are zero.  If INFO > 0, then IFAIL contains the
        indices of the eigenvectors that failed to converge.
        If JOBZ = 'N', then IFAIL is not referenced.
@OBJECT SCALAR I info
INFO    (output) INTEGER
        = 0:  successful exit
        < 0:  if INFO = -i, the i-th argument had an illegal value
        > 0:  DPOTRF or DSYEVX returned an error code:
           <= N:  if INFO = i, DSYEVX failed to converge;
                  i eigenvectors failed to converge.  Their indices
                  are stored in array IFAIL.
           > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                  minor of order i of B is not positive definite.
                  The factorization of B could not be completed and
                  no eigenvalues or eigenvectors were computed.
@COMPLEXITY 2,3
@CALLINGSEQUENCE
@ARG I0
@ARG I1
@ARG I2
@ARG I3
@ARG mI4,nI4,mI5,nI5
@ARG I4,O0
@ARG lI4,lO0
@ARG I5,O1
@ARG lI5,lO1
@ARG I6
@ARG I7
@ARG I8
@ARG I9
@ARG I10
@ARG O2
@ARG O3
@ARG O4
@ARG lO4
@ARG ?
@ARG ?
@ARG ?
@ARG O5
@ARG O6
@CODE
extern void dsygvx(int *itype, char *jobz, char *range, char *uplo,
                   int *n, double *a, int *lda, double *b, int *ldb,
                   double *vl, double *vu, int *il, int *iu,
                   double *abstol, int *m, double *w, double *z,
                   int *ldz, double *work, int *lwork, int *iwork,
                   int *ifail, int *info);

int lda, ldb, ldz, liwork, lwork, *iwork, nb;
double *work;

if (*@I0@ != 1 && *@I0@ != 2 && *@I0@ != 3)
   return NS_PROT_BAD_VALUES;

if (*@I1@ == 'n' || *@I1@ == 'N')
   *@I1@ = 'N';
else if (*@I1@ == 'v' || *@I1@ == 'V')
   *@I1@ = 'V';
else 
   return NS_PROT_BAD_VALUES;

if (*@I2@ == 'a' || *@I2@ == 'A')
   *@I2@ = 'A';
else if (*@I2@ == 'v' || *@I2@ == 'V')
   *@I2@ = 'V';
else if (*@I2@ == 'i' || *@I2@ == 'I')
   *@I2@ = 'I';
else 
   return NS_PROT_BAD_VALUES;

if (*@I3@ == 'u' || *@I3@ == 'U')
   *@I3@ = 'U';
else if (*@I3@ == 'l' || *@I3@ == 'L')
   *@I3@ = 'L';
else 
   return NS_PROT_BAD_VALUES;

lda = (*@mI4@ > 1) ? *@mI4@ : 1;
ldb = (*@mI5@ > 1) ? *@mI5@ : 1;
ldz = (*@nI5@ > 1) ? *@nI5@ : 1;

nb = 64;
lwork = ( (nb + 3) * *@nI5@ > 1) ? (nb + 3) * *@nI5@ : 1;
liwork = (5 * *@nI5@ > 1) ? 5 * *@nI5@ : 1;

work = (double *) malloc(sizeof(double) * lwork);
iwork = (int *) malloc(sizeof(int) * liwork);

@O2@ = (int *) malloc(sizeof(int));
@O3@ = (double *) malloc(sizeof(double) * *@nI5@);
@O4@ = (double *) malloc(sizeof(double) * ldz * *@nI5@);
@O5@ = (int *) malloc(sizeof(int) * *@nI5@);
@O6@ = (int *) malloc(sizeof(int));

dsygvx(@I0@, @I1@, @I2@, @I3@, @nI5@, @I4@, &lda,
       @I5@, &ldb, @I6@, @I7@, @I8@, @I9@, @I10@, @O2@, @O3@, @O4@, &ldz,
       work, &lwork, iwork, @O5@, @O6@);

@O0@ = @I4@;
*@mO0@ = *@mI4@;
*@nO0@ = *@nI4@;

@O1@ = @I5@;
*@mO1@ = *@mI5@;
*@nO1@ = *@nI5@;

*@mO3@ = *@nI5@;

*@mO4@ = *@mI5@;
*@nO4@ = *@nI5@;

*@mO5@ = *@nI5@;
@END_CODE

#
# LAPACK Auxiliary routines
# 
# This file includes problem specifications for the following
# auxiliary routines:
#
# DLACPY
#

@PROBLEM dlacpy

@FUNCTION dlacpy

@LANGUAGE FORTRAN

@MAJOR COL

@PATH /LAPACK/Auxiliary/

@DESCRIPTION
DLACPY copies an M-by-N matrix B to A

    A = B

You can specify "U" or "L" if you want either the
upper or lower triangle copied only.

@INPUT 3

@OBJECT SCALAR CHAR uplo
uplo	(input) CHARACTER*1
	Specifies which part of the matrix to copy:
	= 'U':  Upper triangle only
	= 'L':  Lower triangle only
	otherwise:  All of the matrix

@OBJECT MATRIX D b
B	(input)	DOUBLE PRECISION array, source of data

@OBJECT MATRIX D a
A	(output) DOUBLE PRECISION array, destination for data

@OUTPUT 1

@OBJECT MATRIX D a
A	(output) DOUBLE PRECISION array, destination for data

@COMPLEXITY 2,2

@CALLINGSEQUENCE
@ARG I0
@ARG O0,I2
@ARG I1
@ARG mI1,mI2,lI1,lI2
@ARG nI1,nI2

@CODE
extern void dlacpy(const char * uplo, int *m, int *n, 
			double * a, int *lda, double * b, int *ldb);

dlacpy(@I0@, @mI1@, @nI1@, @I1@, @mI1@, @I2@, @mI1@);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

@END_CODE

##############
# linsol
#   Simplified version of dgesv
##############
@PROBLEM linsol
@FUNCTION dgesv
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK-wrapper/Simple/Linear_Equations/
@DESCRIPTION
Wrapper around the LAPACK routine DGESV --

Compute the solution to a real system of linear equations
  A * X = b
where A is an N-by-B matrix and X and B are N-by-NRHS matrices.

MATLAB Example : [x] = netsolve('linsol',a,b)

@INPUT 2
@OBJECT MATRIX D A
Matrix A
@OBJECT MATRIX D RHS
Right hand side

@OUTPUT 1
@OBJECT MATRIX D SOLUTION
Solution

@COMPLEXITY 2,3

@CALLINGSEQUENCE
@ARG mI0,nI0,mI1
@ARG nI1
@ARG I0
@ARG lI0
@ARG I1,O0
@ARG lI1
@CODE
extern void dgesv(int *n, int *nrhs, double *a, int *lda, int *ipiv,
                  double *b, int *ldb, int *info);

int info;
int *ipiv=NULL;

int lda, ldb;

lda = (*@mI0@ > 1) ? *@mI0@ : 1;
ldb = (*@mI0@ > 1) ? *@mI0@ : 1;

if (*@nI0@ != *@mI0@)
  return NS_PROT_DIM_MISMATCH;
if (*@mI0@ != *@mI1@)
  return NS_PROT_DIM_MISMATCH;

ipiv = (int *)malloc(sizeof(int)*(*@mI0@));

dgesv(@nI0@, @nI1@, @I0@, &lda, ipiv, @I1@, &ldb, &info);

@O0@ = @I1@;
*@mO0@ = *@mI1@;
*@nO0@ = *@nI1@;

if (info >0)
  return NS_PROT_NO_SOLUTION;
if (info <0)
  return NS_PROT_SV_FAILURE;

@END_CODE

##############
# eig
#   Simplified version of dgeev
##############

@PROBLEM eig
@FUNCTION dgeev
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /LAPACK-wrapper/Simple/Eig_and_Singular/
@DESCRIPTION
Wrapper around the LAPACK routine DGEEV --

Simplified version of DGEEV.
Computes the eigenvalues of a double precision real
matrix A. Returns two double precision real
vectors containing respectively the real parts and
the imaginary parts of the eigenvalues.

MATLAB Example : [r i ] = netsolve('eig',a)

@INPUT 1
@OBJECT MATRIX D A
Matrix A
@OUTPUT 2
@OBJECT VECTOR D R
Real parts of the eigen values
@OBJECT VECTOR D I
Imaginary parts of the eigen values

@MATLAB_MERGE 0 1

@COMPLEXITY 3,2

@CALLINGSEQUENCE
@ARG I0
@ARG nI0,mI0
@ARG lI0
@ARG O0
@ARG O1
@ARG ?
@ARG ?

@CODE
extern void dgeev(char *jobvl, char *jobvr, int *n, double *a, int *lda,
                  double *wr, double *wi, double *vl, int *ldvl, 
                  double *vr, int *ldvr, double *work, int *lwork,
                  int *info);

int info;
double *work = NULL;
double *vr,*vl;
int lwork;
char c1,c2;

if (*@mI0@ != *@nI0@)
  return NS_PROT_DIM_MISMATCH;

*@mO0@ = *@mI0@;
*@mO1@ = *@mI0@;

@O0@ = (double *)malloc(sizeof(double)*(*@mI0@));
@O1@ = (double *)malloc(sizeof(double)*(*@mI0@));
vl = NULL;
vr = NULL;

lwork = 3*(*@mI0@);

work = (double *)malloc(sizeof(double)*lwork);
c1 = 'N'; c2 = 'N';

dgeev(&c1,&c2,@mI0@,@I0@,@mI0@,@O0@,@O1@,(double *)vl,
      @mI0@,(double *)vr,@mI0@,
     (double *)work,&lwork,&info);

if (info >0)
  return NS_PROT_NO_SOLUTION;
if (info <0)
  return NS_PROT_SV_FAILURE;

@END_CODE
