Example #1
0
        public void Run(int N, double DA, ref double[] DX, int offset_dx, int INCX)
        {
            #region Variables

            int I = 0; int M = 0; int MP1 = 0; int NINCX = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;

            #endregion

            // c
            // c     scales a vector by a constant.
            // c     uses unrolled loops for increment equal to one.
            // c     jack dongarra, linpack, 3/11/78.
            // c     modified 3/93 to return if incx .le. 0.
            // c
            // c

            #region Body

            if (N <= 0 || INCX <= 0)
            {
                return;
            }
            if (INCX == 1)
            {
                goto LABEL20;
            }
            // c
            // c        code for increment not equal to 1
            // c
            NINCX = N * INCX;
            for (I = 1; (INCX >= 0) ? (I <= NINCX) : (I >= NINCX); I += INCX)
            {
                DX[I + o_dx] *= DA;
            }
            return;

            // c
            // c        code for increment equal to 1
            // c
            // c
            // c        clean-up loop
            // c
            LABEL20 :  M = FortranLib.Mod(N, 5);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DX[I + o_dx] *= DA;
            }
            if (N < 5)
            {
                return;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 5)
            {
                DX[I + o_dx]     *= DA;
                DX[I + 1 + o_dx] *= DA;
                DX[I + 2 + o_dx] *= DA;
                DX[I + 3 + o_dx] *= DA;
                DX[I + 4 + o_dx] *= DA;
            }
            return;

            #endregion
        }
Example #2
0
        public double Run(int N, double[] DX, int offset_dx, int INCX, double[] DY, int offset_dy, int INCY)
        {
            double ddot = 0;

            #region Variables

            double DTEMP = 0; int I = 0; int IX = 0; int IY = 0; int M = 0; int MP1 = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;  int o_dy = -1 + offset_dy;

            #endregion

            // c
            // c     forms the dot product of two vectors.
            // c     uses unrolled loops for increments equal to one.
            // c     jack dongarra, linpack, 3/11/78.
            // c
            // c

            #region Body

            ddot  = 0.0E0;
            DTEMP = 0.0E0;
            if (N <= 0)
            {
                return(ddot);
            }
            if (INCX == 1 && INCY == 1)
            {
                goto LABEL20;
            }
            // c
            // c        code for unequal increments or equal increments
            // c          not equal to 1
            // c
            IX = 1;
            IY = 1;
            if (INCX < 0)
            {
                IX = (-N + 1) * INCX + 1;
            }
            if (INCY < 0)
            {
                IY = (-N + 1) * INCY + 1;
            }
            for (I = 1; I <= N; I++)
            {
                DTEMP += DX[IX + o_dx] * DY[IY + o_dy];
                IX    += INCX;
                IY    += INCY;
            }
            ddot = DTEMP;
            return(ddot);

            // c
            // c        code for both increments equal to 1
            // c
            // c
            // c        clean-up loop
            // c
            LABEL20 :  M = FortranLib.Mod(N, 5);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DTEMP += DX[I + o_dx] * DY[I + o_dy];
            }
            if (N < 5)
            {
                goto LABEL60;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 5)
            {
                DTEMP += DX[I + o_dx] * DY[I + o_dy] + DX[I + 1 + o_dx] * DY[I + 1 + o_dy] + DX[I + 2 + o_dx] * DY[I + 2 + o_dy] + DX[I + 3 + o_dx] * DY[I + 3 + o_dy] + DX[I + 4 + o_dx] * DY[I + 4 + o_dy];
            }
            LABEL60 :  ddot = DTEMP;
            return(ddot);

            #endregion
        }
Example #3
0
        public void Run(int N, int M, ref double[] WS, int offset_ws, ref double[] WY, int offset_wy, ref double[] SY, int offset_sy, ref double[] SS, int offset_ss
                        , double[] D, int offset_d, double[] R, int offset_r, ref int ITAIL, int IUPDAT, ref int COL, ref int HEAD
                        , ref double THETA, double RR, double DR, double STP, double DTD)
        {
            #region Variables

            int J = 0; int POINTR = 0; double DDOT = 0;

            #endregion


            #region Implicit Variables

            int SS_COL = 0;

            #endregion


            #region Array Index Correction

            int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;  int o_sy = -1 - M + offset_sy;
            int o_ss = -1 - M + offset_ss; int o_d = -1 + offset_d;  int o_r = -1 + offset_r;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine matupd
            // c
            // c       This subroutine updates matrices WS and WY, and forms the
            // c         middle matrix in B.
            // c
            // c     Subprograms called:
            // c
            // c       Linpack ... dcopy, ddot.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            // c     Set pointers for matrices WS and WY.


            #endregion


            #region Body

            if (IUPDAT <= M)
            {
                COL   = IUPDAT;
                ITAIL = FortranLib.Mod(HEAD + IUPDAT - 2, M) + 1;
            }
            else
            {
                ITAIL = FortranLib.Mod(ITAIL, M) + 1;
                HEAD  = FortranLib.Mod(HEAD, M) + 1;
            }

            // c     Update matrices WS and WY.

            this._dcopy.Run(N, D, offset_d, 1, ref WS, 1 + ITAIL * N + o_ws, 1);
            this._dcopy.Run(N, R, offset_r, 1, ref WY, 1 + ITAIL * N + o_wy, 1);

            // c     Set theta=yy/ys.

            THETA = RR / DR;

            // c     Form the middle matrix in B.

            // c        update the upper triangle of SS,
            // c                                         and the lower triangle of SY:
            if (IUPDAT > M)
            {
                // c                              move old information
                for (J = 1; J <= COL - 1; J++)
                {
                    this._dcopy.Run(J, SS, 2 + (J + 1) * M + o_ss, 1, ref SS, 1 + J * M + o_ss, 1);
                    this._dcopy.Run(COL - J, SY, J + 1 + (J + 1) * M + o_sy, 1, ref SY, J + J * M + o_sy, 1);
                }
            }
            // c        add new information: the last row of SY
            // c                                             and the last column of SS:
            POINTR = HEAD;
            SS_COL = COL * M + o_ss;
            for (J = 1; J <= COL - 1; J++)
            {
                SY[COL + J * M + o_sy] = this._ddot.Run(N, D, offset_d, 1, WY, 1 + POINTR * N + o_wy, 1);
                SS[J + SS_COL]         = this._ddot.Run(N, WS, 1 + POINTR * N + o_ws, 1, D, offset_d, 1);
                POINTR = FortranLib.Mod(POINTR, M) + 1;
            }
            if (STP == ONE)
            {
                SS[COL + COL * M + o_ss] = DTD;
            }
            else
            {
                SS[COL + COL * M + o_ss] = STP * STP * DTD;
            }
            SY[COL + COL * M + o_sy] = DR;

            return;


            #endregion
        }
Example #4
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// DLAQR0 computes the eigenvalues of a Hessenberg matrix H
        /// and, optionally, the matrices T and Z from the Schur decomposition
        /// H = Z T Z**T, where T is an upper quasi-triangular matrix (the
        /// Schur form), and Z is the orthogonal matrix of Schur vectors.
        ///
        /// Optionally Z may be postmultiplied into an input orthogonal
        /// matrix Q so that this routine can give the Schur factorization
        /// of a matrix A which has been reduced to the Hessenberg form H
        /// by the orthogonal matrix Q:  A = Q*H*Q**T = (QZ)*T*(QZ)**T.
        ///
        ///</summary>
        /// <param name="WANTT">
        /// (input) LOGICAL
        /// = .TRUE. : the full Schur form T is required;
        /// = .FALSE.: only eigenvalues are required.
        ///</param>
        /// <param name="WANTZ">
        /// (input) LOGICAL
        /// = .TRUE. : the matrix of Schur vectors Z is required;
        /// = .FALSE.: Schur vectors are not required.
        ///</param>
        /// <param name="N">
        /// (input) INTEGER
        /// The order of the matrix H.  N .GE. 0.
        ///</param>
        /// <param name="ILO">
        /// (input) INTEGER
        ///</param>
        /// <param name="IHI">
        /// (input) INTEGER
        /// It is assumed that H is already upper triangular in rows
        /// and columns 1:ILO-1 and IHI+1:N and, if ILO.GT.1,
        /// H(ILO,ILO-1) is zero. ILO and IHI are normally set by a
        /// previous call to DGEBAL, and then passed to DGEHRD when the
        /// matrix output by DGEBAL is reduced to Hessenberg form.
        /// Otherwise, ILO and IHI should be set to 1 and N,
        /// respectively.  If N.GT.0, then 1.LE.ILO.LE.IHI.LE.N.
        /// If N = 0, then ILO = 1 and IHI = 0.
        ///</param>
        /// <param name="H">
        /// (input/output) DOUBLE PRECISION array, dimension (LDH,N)
        /// On entry, the upper Hessenberg matrix H.
        /// On exit, if INFO = 0 and WANTT is .TRUE., then H contains
        /// the upper quasi-triangular matrix T from the Schur
        /// decomposition (the Schur form); 2-by-2 diagonal blocks
        /// (corresponding to complex conjugate pairs of eigenvalues)
        /// are returned in standard form, with H(i,i) = H(i+1,i+1)
        /// and H(i+1,i)*H(i,i+1).LT.0. If INFO = 0 and WANTT is
        /// .FALSE., then the contents of H are unspecified on exit.
        /// (The output value of H when INFO.GT.0 is given under the
        /// description of INFO below.)
        ///
        /// This subroutine may explicitly set H(i,j) = 0 for i.GT.j and
        /// j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N.
        ///</param>
        /// <param name="LDH">
        /// (input) INTEGER
        /// The leading dimension of the array H. LDH .GE. max(1,N).
        ///</param>
        /// <param name="WR">
        /// (output) DOUBLE PRECISION array, dimension (IHI)
        ///</param>
        /// <param name="WI">
        /// (output) DOUBLE PRECISION array, dimension (IHI)
        /// The real and imaginary parts, respectively, of the computed
        /// eigenvalues of H(ILO:IHI,ILO:IHI) are stored WR(ILO:IHI)
        /// and WI(ILO:IHI). If two eigenvalues are computed as a
        /// complex conjugate pair, they are stored in consecutive
        /// elements of WR and WI, say the i-th and (i+1)th, with
        /// WI(i) .GT. 0 and WI(i+1) .LT. 0. If WANTT is .TRUE., then
        /// the eigenvalues are stored in the same order as on the
        /// diagonal of the Schur form returned in H, with
        /// WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal
        /// block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and
        /// WI(i+1) = -WI(i).
        ///</param>
        /// <param name="ILOZ">
        /// (input) INTEGER
        ///</param>
        /// <param name="IHIZ">
        /// (input) INTEGER
        /// Specify the rows of Z to which transformations must be
        /// applied if WANTZ is .TRUE..
        /// 1 .LE. ILOZ .LE. ILO; IHI .LE. IHIZ .LE. N.
        ///</param>
        /// <param name="Z">
        /// (input/output) DOUBLE PRECISION array, dimension (LDZ,IHI)
        /// If WANTZ is .FALSE., then Z is not referenced.
        /// If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is
        /// replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the
        /// orthogonal Schur factor of H(ILO:IHI,ILO:IHI).
        /// (The output value of Z when INFO.GT.0 is given under
        /// the description of INFO below.)
        ///</param>
        /// <param name="LDZ">
        /// (input) INTEGER
        /// The leading dimension of the array Z.  if WANTZ is .TRUE.
        /// then LDZ.GE.MAX(1,IHIZ).  Otherwize, LDZ.GE.1.
        ///</param>
        /// <param name="WORK">
        /// (workspace/output) DOUBLE PRECISION array, dimension LWORK
        /// On exit, if LWORK = -1, WORK(1) returns an estimate of
        /// the optimal value for LWORK.
        ///</param>
        /// <param name="LWORK">
        /// (input) INTEGER
        /// The dimension of the array WORK.  LWORK .GE. max(1,N)
        /// is sufficient, but LWORK typically as large as 6*N may
        /// be required for optimal performance.  A workspace query
        /// to determine the optimal workspace size is recommended.
        ///
        /// If LWORK = -1, then DLAQR0 does a workspace query.
        /// In this case, DLAQR0 checks the input parameters and
        /// estimates the optimal workspace size for the given
        /// values of N, ILO and IHI.  The estimate is returned
        /// in WORK(1).  No error message related to LWORK is
        /// issued by XERBLA.  Neither H nor Z are accessed.
        ///
        ///</param>
        /// <param name="INFO">
        /// (output) INTEGER
        /// =  0:  successful exit
        /// .GT. 0:  if INFO = i, DLAQR0 failed to compute all of
        /// the eigenvalues.  Elements 1:ilo-1 and i+1:n of WR
        /// and WI contain those eigenvalues which have been
        /// successfully computed.  (Failures are rare.)
        ///
        /// If INFO .GT. 0 and WANT is .FALSE., then on exit,
        /// the remaining unconverged eigenvalues are the eigen-
        /// values of the upper Hessenberg matrix rows and
        /// columns ILO through INFO of the final, output
        /// value of H.
        ///
        /// If INFO .GT. 0 and WANTT is .TRUE., then on exit
        ///
        /// (*)  (initial value of H)*U  = U*(final value of H)
        ///
        /// where U is an orthogonal matrix.  The final
        /// value of H is upper Hessenberg and quasi-triangular
        /// in rows and columns INFO+1 through IHI.
        ///
        /// If INFO .GT. 0 and WANTZ is .TRUE., then on exit
        ///
        /// (final value of Z(ILO:IHI,ILOZ:IHIZ)
        /// =  (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U
        ///
        /// where U is the orthogonal matrix in (*) (regard-
        /// less of the value of WANTT.)
        ///
        /// If INFO .GT. 0 and WANTZ is .FALSE., then Z is not
        /// accessed.
        ///
        ///</param>
        public void Run(bool WANTT, bool WANTZ, int N, int ILO, int IHI, ref double[] H, int offset_h
                        , int LDH, ref double[] WR, int offset_wr, ref double[] WI, int offset_wi, int ILOZ, int IHIZ, ref double[] Z, int offset_z
                        , int LDZ, ref double[] WORK, int offset_work, int LWORK, ref int INFO)
        {
            #region Variables

            double AA = 0; double BB = 0; double CC = 0; double CS = 0; double DD = 0; double SN = 0; double SS = 0;
            double SWAP = 0; int I = 0; int INF = 0; int IT = 0; int ITMAX = 0; int K = 0; int KACC22 = 0; int KBOT = 0;
            int    KDU = 0; int KS = 0; int KT = 0; int KTOP = 0; int KU = 0; int KV = 0; int KWH = 0; int KWTOP = 0; int KWV = 0;
            int    LD = 0; int LS = 0; int LWKOPT = 0; int NDFL = 0; int NH = 0; int NHO = 0; int NIBBLE = 0; int NMIN = 0;
            int    NS = 0; int NSMAX = 0; int NSR = 0; int NVE = 0; int NW = 0; int NWMAX = 0; int NWR = 0; bool NWINC = false;
            bool   SORTED = false; string JBCMPZ = new string(' ', 2); int offset_zdum = 0;

            #endregion


            #region Array Index Correction

            int o_h = -1 - LDH + offset_h;  int o_wr = -1 + offset_wr;  int o_wi = -1 + offset_wi;
            int o_z = -1 - LDZ + offset_z; int o_work = -1 + offset_work;

            #endregion


            #region Prolog

            // *
            // *  -- LAPACK auxiliary routine (version 3.1) --
            // *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
            // *     November 2006
            // *
            // *     .. Scalar Arguments ..
            // *     ..
            // *     .. Array Arguments ..
            // *     ..
            // *
            // *     Purpose
            // *     =======
            // *
            // *     DLAQR0 computes the eigenvalues of a Hessenberg matrix H
            // *     and, optionally, the matrices T and Z from the Schur decomposition
            // *     H = Z T Z**T, where T is an upper quasi-triangular matrix (the
            // *     Schur form), and Z is the orthogonal matrix of Schur vectors.
            // *
            // *     Optionally Z may be postmultiplied into an input orthogonal
            // *     matrix Q so that this routine can give the Schur factorization
            // *     of a matrix A which has been reduced to the Hessenberg form H
            // *     by the orthogonal matrix Q:  A = Q*H*Q**T = (QZ)*T*(QZ)**T.
            // *
            // *     Arguments
            // *     =========
            // *
            // *     WANTT   (input) LOGICAL
            // *          = .TRUE. : the full Schur form T is required;
            // *          = .FALSE.: only eigenvalues are required.
            // *
            // *     WANTZ   (input) LOGICAL
            // *          = .TRUE. : the matrix of Schur vectors Z is required;
            // *          = .FALSE.: Schur vectors are not required.
            // *
            // *     N     (input) INTEGER
            // *           The order of the matrix H.  N .GE. 0.
            // *
            // *     ILO   (input) INTEGER
            // *     IHI   (input) INTEGER
            // *           It is assumed that H is already upper triangular in rows
            // *           and columns 1:ILO-1 and IHI+1:N and, if ILO.GT.1,
            // *           H(ILO,ILO-1) is zero. ILO and IHI are normally set by a
            // *           previous call to DGEBAL, and then passed to DGEHRD when the
            // *           matrix output by DGEBAL is reduced to Hessenberg form.
            // *           Otherwise, ILO and IHI should be set to 1 and N,
            // *           respectively.  If N.GT.0, then 1.LE.ILO.LE.IHI.LE.N.
            // *           If N = 0, then ILO = 1 and IHI = 0.
            // *
            // *     H     (input/output) DOUBLE PRECISION array, dimension (LDH,N)
            // *           On entry, the upper Hessenberg matrix H.
            // *           On exit, if INFO = 0 and WANTT is .TRUE., then H contains
            // *           the upper quasi-triangular matrix T from the Schur
            // *           decomposition (the Schur form); 2-by-2 diagonal blocks
            // *           (corresponding to complex conjugate pairs of eigenvalues)
            // *           are returned in standard form, with H(i,i) = H(i+1,i+1)
            // *           and H(i+1,i)*H(i,i+1).LT.0. If INFO = 0 and WANTT is
            // *           .FALSE., then the contents of H are unspecified on exit.
            // *           (The output value of H when INFO.GT.0 is given under the
            // *           description of INFO below.)
            // *
            // *           This subroutine may explicitly set H(i,j) = 0 for i.GT.j and
            // *           j = 1, 2, ... ILO-1 or j = IHI+1, IHI+2, ... N.
            // *
            // *     LDH   (input) INTEGER
            // *           The leading dimension of the array H. LDH .GE. max(1,N).
            // *
            // *     WR    (output) DOUBLE PRECISION array, dimension (IHI)
            // *     WI    (output) DOUBLE PRECISION array, dimension (IHI)
            // *           The real and imaginary parts, respectively, of the computed
            // *           eigenvalues of H(ILO:IHI,ILO:IHI) are stored WR(ILO:IHI)
            // *           and WI(ILO:IHI). If two eigenvalues are computed as a
            // *           complex conjugate pair, they are stored in consecutive
            // *           elements of WR and WI, say the i-th and (i+1)th, with
            // *           WI(i) .GT. 0 and WI(i+1) .LT. 0. If WANTT is .TRUE., then
            // *           the eigenvalues are stored in the same order as on the
            // *           diagonal of the Schur form returned in H, with
            // *           WR(i) = H(i,i) and, if H(i:i+1,i:i+1) is a 2-by-2 diagonal
            // *           block, WI(i) = sqrt(-H(i+1,i)*H(i,i+1)) and
            // *           WI(i+1) = -WI(i).
            // *
            // *     ILOZ     (input) INTEGER
            // *     IHIZ     (input) INTEGER
            // *           Specify the rows of Z to which transformations must be
            // *           applied if WANTZ is .TRUE..
            // *           1 .LE. ILOZ .LE. ILO; IHI .LE. IHIZ .LE. N.
            // *
            // *     Z     (input/output) DOUBLE PRECISION array, dimension (LDZ,IHI)
            // *           If WANTZ is .FALSE., then Z is not referenced.
            // *           If WANTZ is .TRUE., then Z(ILO:IHI,ILOZ:IHIZ) is
            // *           replaced by Z(ILO:IHI,ILOZ:IHIZ)*U where U is the
            // *           orthogonal Schur factor of H(ILO:IHI,ILO:IHI).
            // *           (The output value of Z when INFO.GT.0 is given under
            // *           the description of INFO below.)
            // *
            // *     LDZ   (input) INTEGER
            // *           The leading dimension of the array Z.  if WANTZ is .TRUE.
            // *           then LDZ.GE.MAX(1,IHIZ).  Otherwize, LDZ.GE.1.
            // *
            // *     WORK  (workspace/output) DOUBLE PRECISION array, dimension LWORK
            // *           On exit, if LWORK = -1, WORK(1) returns an estimate of
            // *           the optimal value for LWORK.
            // *
            // *     LWORK (input) INTEGER
            // *           The dimension of the array WORK.  LWORK .GE. max(1,N)
            // *           is sufficient, but LWORK typically as large as 6*N may
            // *           be required for optimal performance.  A workspace query
            // *           to determine the optimal workspace size is recommended.
            // *
            // *           If LWORK = -1, then DLAQR0 does a workspace query.
            // *           In this case, DLAQR0 checks the input parameters and
            // *           estimates the optimal workspace size for the given
            // *           values of N, ILO and IHI.  The estimate is returned
            // *           in WORK(1).  No error message related to LWORK is
            // *           issued by XERBLA.  Neither H nor Z are accessed.
            // *
            // *
            // *     INFO  (output) INTEGER
            // *             =  0:  successful exit
            // *           .GT. 0:  if INFO = i, DLAQR0 failed to compute all of
            // *                the eigenvalues.  Elements 1:ilo-1 and i+1:n of WR
            // *                and WI contain those eigenvalues which have been
            // *                successfully computed.  (Failures are rare.)
            // *
            // *                If INFO .GT. 0 and WANT is .FALSE., then on exit,
            // *                the remaining unconverged eigenvalues are the eigen-
            // *                values of the upper Hessenberg matrix rows and
            // *                columns ILO through INFO of the final, output
            // *                value of H.
            // *
            // *                If INFO .GT. 0 and WANTT is .TRUE., then on exit
            // *
            // *           (*)  (initial value of H)*U  = U*(final value of H)
            // *
            // *                where U is an orthogonal matrix.  The final
            // *                value of H is upper Hessenberg and quasi-triangular
            // *                in rows and columns INFO+1 through IHI.
            // *
            // *                If INFO .GT. 0 and WANTZ is .TRUE., then on exit
            // *
            // *                  (final value of Z(ILO:IHI,ILOZ:IHIZ)
            // *                   =  (initial value of Z(ILO:IHI,ILOZ:IHIZ)*U
            // *
            // *                where U is the orthogonal matrix in (*) (regard-
            // *                less of the value of WANTT.)
            // *
            // *                If INFO .GT. 0 and WANTZ is .FALSE., then Z is not
            // *                accessed.
            // *
            // *
            // *     ================================================================
            // *     Based on contributions by
            // *        Karen Braman and Ralph Byers, Department of Mathematics,
            // *        University of Kansas, USA
            // *
            // *     ================================================================
            // *
            // *     References:
            // *       K. Braman, R. Byers and R. Mathias, The Multi-Shift QR
            // *       Algorithm Part I: Maintaining Well Focused Shifts, and Level 3
            // *       Performance, SIAM Journal of Matrix Analysis, volume 23, pages
            // *       929--947, 2002.
            // *
            // *       K. Braman, R. Byers and R. Mathias, The Multi-Shift QR
            // *       Algorithm Part II: Aggressive Early Deflation, SIAM Journal
            // *       of Matrix Analysis, volume 23, pages 948--973, 2002.
            // *
            // *     ================================================================
            // *     .. Parameters ..
            // *
            // *     ==== Matrices of order NTINY or smaller must be processed by
            // *     .    DLAHQR because of insufficient subdiagonal scratch space.
            // *     .    (This is a hard limit.) ====
            // *
            // *     ==== Exceptional deflation windows:  try to cure rare
            // *     .    slow convergence by increasing the size of the
            // *     .    deflation window after KEXNW iterations. =====
            // *
            // *     ==== Exceptional shifts: try to cure rare slow convergence
            // *     .    with ad-hoc exceptional shifts every KEXSH iterations.
            // *     .    The constants WILK1 and WILK2 are used to form the
            // *     .    exceptional shifts. ====
            // *
            // *     ..
            // *     .. Local Scalars ..
            // *     ..
            // *     .. External Functions ..
            // *     ..
            // *     .. Local Arrays ..
            // *     ..
            // *     .. External Subroutines ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC          ABS, DBLE, INT, MAX, MIN, MOD;
            // *     ..
            // *     .. Executable Statements ..

            #endregion


            #region Body

            INFO = 0;
            // *
            // *     ==== Quick return for N = 0: nothing to do. ====
            // *
            if (N == 0)
            {
                WORK[1 + o_work] = ONE;
                return;
            }
            // *
            // *     ==== Set up job flags for ILAENV. ====
            // *
            if (WANTT)
            {
                FortranLib.Copy(ref JBCMPZ, 1, 1, "S");
            }
            else
            {
                FortranLib.Copy(ref JBCMPZ, 1, 1, "E");
            }
            if (WANTZ)
            {
                FortranLib.Copy(ref JBCMPZ, 2, 2, "V");
            }
            else
            {
                FortranLib.Copy(ref JBCMPZ, 2, 2, "N");
            }
            // *
            // *     ==== Tiny matrices must use DLAHQR. ====
            // *
            if (N <= NTINY)
            {
                // *
                // *        ==== Estimate optimal workspace. ====
                // *
                LWKOPT = 1;
                if (LWORK != -1)
                {
                    this._dlahqr.Run(WANTT, WANTZ, N, ILO, IHI, ref H, offset_h
                                     , LDH, ref WR, offset_wr, ref WI, offset_wi, ILOZ, IHIZ, ref Z, offset_z
                                     , LDZ, ref INFO);
                }
            }
            else
            {
                // *
                // *        ==== Use small bulge multi-shift QR with aggressive early
                // *        .    deflation on larger-than-tiny matrices. ====
                // *
                // *        ==== Hope for the best. ====
                // *
                INFO = 0;
                // *
                // *        ==== NWR = recommended deflation window size.  At this
                // *        .    point,  N .GT. NTINY = 11, so there is enough
                // *        .    subdiagonal workspace for NWR.GE.2 as required.
                // *        .    (In fact, there is enough subdiagonal space for
                // *        .    NWR.GE.3.) ====
                // *
                NWR = this._ilaenv.Run(13, "DLAQR0", JBCMPZ, N, ILO, IHI, LWORK);
                NWR = Math.Max(2, NWR);
                NWR = Math.Min(IHI - ILO + 1, Math.Min((N - 1) / 3, NWR));
                NW  = NWR;
                // *
                // *        ==== NSR = recommended number of simultaneous shifts.
                // *        .    At this point N .GT. NTINY = 11, so there is at
                // *        .    enough subdiagonal workspace for NSR to be even
                // *        .    and greater than or equal to two as required. ====
                // *
                NSR = this._ilaenv.Run(15, "DLAQR0", JBCMPZ, N, ILO, IHI, LWORK);
                NSR = Math.Min(NSR, Math.Min((N + 6) / 9, IHI - ILO));
                NSR = Math.Max(2, NSR - FortranLib.Mod(NSR, 2));
                // *
                // *        ==== Estimate optimal workspace ====
                // *
                // *        ==== Workspace query call to DLAQR3 ====
                // *
                this._dlaqr3.Run(WANTT, WANTZ, N, ILO, IHI, NWR + 1
                                 , ref H, offset_h, LDH, ILOZ, IHIZ, ref Z, offset_z, LDZ
                                 , ref LS, ref LD, ref WR, offset_wr, ref WI, offset_wi, ref H, offset_h, LDH
                                 , N, ref H, offset_h, LDH, N, ref H, offset_h, LDH
                                 , ref WORK, offset_work, -1);
                // *
                // *        ==== Optimal workspace = MAX(DLAQR5, DLAQR3) ====
                // *
                LWKOPT = Math.Max(3 * NSR / 2, Convert.ToInt32(Math.Truncate(WORK[1 + o_work])));
                // *
                // *        ==== Quick return in case of workspace query. ====
                // *
                if (LWORK == -1)
                {
                    WORK[1 + o_work] = Convert.ToDouble(LWKOPT);
                    return;
                }
                // *
                // *        ==== DLAHQR/DLAQR0 crossover point ====
                // *
                NMIN = this._ilaenv.Run(12, "DLAQR0", JBCMPZ, N, ILO, IHI, LWORK);
                NMIN = Math.Max(NTINY, NMIN);
                // *
                // *        ==== Nibble crossover point ====
                // *
                NIBBLE = this._ilaenv.Run(14, "DLAQR0", JBCMPZ, N, ILO, IHI, LWORK);
                NIBBLE = Math.Max(0, NIBBLE);
                // *
                // *        ==== Accumulate reflections during ttswp?  Use block
                // *        .    2-by-2 structure during matrix-matrix multiply? ====
                // *
                KACC22 = this._ilaenv.Run(16, "DLAQR0", JBCMPZ, N, ILO, IHI, LWORK);
                KACC22 = Math.Max(0, KACC22);
                KACC22 = Math.Min(2, KACC22);
                // *
                // *        ==== NWMAX = the largest possible deflation window for
                // *        .    which there is sufficient workspace. ====
                // *
                NWMAX = Math.Min((N - 1) / 3, LWORK / 2);
                // *
                // *        ==== NSMAX = the Largest number of simultaneous shifts
                // *        .    for which there is sufficient workspace. ====
                // *
                NSMAX  = Math.Min((N + 6) / 9, 2 * LWORK / 3);
                NSMAX -= FortranLib.Mod(NSMAX, 2);
                // *
                // *        ==== NDFL: an iteration count restarted at deflation. ====
                // *
                NDFL = 1;
                // *
                // *        ==== ITMAX = iteration limit ====
                // *
                ITMAX = Math.Max(30, 2 * KEXSH) * Math.Max(10, (IHI - ILO + 1));
                // *
                // *        ==== Last row and column in the active block ====
                // *
                KBOT = IHI;
                // *
                // *        ==== Main Loop ====
                // *
                for (IT = 1; IT <= ITMAX; IT++)
                {
                    // *
                    // *           ==== Done when KBOT falls below ILO ====
                    // *
                    if (KBOT < ILO)
                    {
                        goto LABEL90;
                    }
                    // *
                    // *           ==== Locate active block ====
                    // *
                    for (K = KBOT; K >= ILO + 1; K += -1)
                    {
                        if (H[K + (K - 1) * LDH + o_h] == ZERO)
                        {
                            goto LABEL20;
                        }
                    }
                    K = ILO;
                    LABEL20 :;
                    KTOP = K;
                    // *
                    // *           ==== Select deflation window size ====
                    // *
                    NH = KBOT - KTOP + 1;
                    if (NDFL < KEXNW || NH < NW)
                    {
                        // *
                        // *              ==== Typical deflation window.  If possible and
                        // *              .    advisable, nibble the entire active block.
                        // *              .    If not, use size NWR or NWR+1 depending upon
                        // *              .    which has the smaller corresponding subdiagonal
                        // *              .    entry (a heuristic). ====
                        // *
                        NWINC = true;
                        if (NH <= Math.Min(NMIN, NWMAX))
                        {
                            NW = NH;
                        }
                        else
                        {
                            NW = Math.Min(NWR, Math.Min(NH, NWMAX));
                            if (NW < NWMAX)
                            {
                                if (NW >= NH - 1)
                                {
                                    NW = NH;
                                }
                                else
                                {
                                    KWTOP = KBOT - NW + 1;
                                    if (Math.Abs(H[KWTOP + (KWTOP - 1) * LDH + o_h]) > Math.Abs(H[KWTOP - 1 + (KWTOP - 2) * LDH + o_h]))
                                    {
                                        NW += 1;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // *
                        // *              ==== Exceptional deflation window.  If there have
                        // *              .    been no deflations in KEXNW or more iterations,
                        // *              .    then vary the deflation window size.   At first,
                        // *              .    because, larger windows are, in general, more
                        // *              .    powerful than smaller ones, rapidly increase the
                        // *              .    window up to the maximum reasonable and possible.
                        // *              .    Then maybe try a slightly smaller window.  ====
                        // *
                        if (NWINC && NW < Math.Min(NWMAX, NH))
                        {
                            NW = Math.Min(NWMAX, Math.Min(NH, 2 * NW));
                        }
                        else
                        {
                            NWINC = false;
                            if (NW == NH && NH > 2)
                            {
                                NW = NH - 1;
                            }
                        }
                    }
                    // *
                    // *           ==== Aggressive early deflation:
                    // *           .    split workspace under the subdiagonal into
                    // *           .      - an nw-by-nw work array V in the lower
                    // *           .        left-hand-corner,
                    // *           .      - an NW-by-at-least-NW-but-more-is-better
                    // *           .        (NW-by-NHO) horizontal work array along
                    // *           .        the bottom edge,
                    // *           .      - an at-least-NW-but-more-is-better (NHV-by-NW)
                    // *           .        vertical work array along the left-hand-edge.
                    // *           .        ====
                    // *
                    KV  = N - NW + 1;
                    KT  = NW + 1;
                    NHO = (N - NW - 1) - KT + 1;
                    KWV = NW + 2;
                    NVE = (N - NW) - KWV + 1;
                    // *
                    // *           ==== Aggressive early deflation ====
                    // *
                    this._dlaqr3.Run(WANTT, WANTZ, N, KTOP, KBOT, NW
                                     , ref H, offset_h, LDH, ILOZ, IHIZ, ref Z, offset_z, LDZ
                                     , ref LS, ref LD, ref WR, offset_wr, ref WI, offset_wi, ref H, KV + 1 * LDH + o_h, LDH
                                     , NHO, ref H, KV + KT * LDH + o_h, LDH, NVE, ref H, KWV + 1 * LDH + o_h, LDH
                                     , ref WORK, offset_work, LWORK);
                    // *
                    // *           ==== Adjust KBOT accounting for new deflations. ====
                    // *
                    KBOT -= LD;
                    // *
                    // *           ==== KS points to the shifts. ====
                    // *
                    KS = KBOT - LS + 1;
                    // *
                    // *           ==== Skip an expensive QR sweep if there is a (partly
                    // *           .    heuristic) reason to expect that many eigenvalues
                    // *           .    will deflate without it.  Here, the QR sweep is
                    // *           .    skipped if many eigenvalues have just been deflated
                    // *           .    or if the remaining active block is small.
                    // *
                    if ((LD == 0) || ((100 * LD <= NW * NIBBLE) && (KBOT - KTOP + 1 > Math.Min(NMIN, NWMAX))))
                    {
                        // *
                        // *              ==== NS = nominal number of simultaneous shifts.
                        // *              .    This may be lowered (slightly) if DLAQR3
                        // *              .    did not provide that many shifts. ====
                        // *
                        NS  = Math.Min(NSMAX, Math.Min(NSR, Math.Max(2, KBOT - KTOP)));
                        NS -= FortranLib.Mod(NS, 2);
                        // *
                        // *              ==== If there have been no deflations
                        // *              .    in a multiple of KEXSH iterations,
                        // *              .    then try exceptional shifts.
                        // *              .    Otherwise use shifts provided by
                        // *              .    DLAQR3 above or from the eigenvalues
                        // *              .    of a trailing principal submatrix. ====
                        // *
                        if (FortranLib.Mod(NDFL, KEXSH) == 0)
                        {
                            KS = KBOT - NS + 1;
                            for (I = KBOT; I >= Math.Max(KS + 1, KTOP + 2); I += -2)
                            {
                                SS = Math.Abs(H[I + (I - 1) * LDH + o_h]) + Math.Abs(H[I - 1 + (I - 2) * LDH + o_h]);
                                AA = WILK1 * SS + H[I + I * LDH + o_h];
                                BB = SS;
                                CC = WILK2 * SS;
                                DD = AA;
                                this._dlanv2.Run(ref AA, ref BB, ref CC, ref DD, ref WR[I - 1 + o_wr], ref WI[I - 1 + o_wi]
                                                 , ref WR[I + o_wr], ref WI[I + o_wi], ref CS, ref SN);
                            }
                            if (KS == KTOP)
                            {
                                WR[KS + 1 + o_wr] = H[KS + 1 + (KS + 1) * LDH + o_h];
                                WI[KS + 1 + o_wi] = ZERO;
                                WR[KS + o_wr]     = WR[KS + 1 + o_wr];
                                WI[KS + o_wi]     = WI[KS + 1 + o_wi];
                            }
                        }
                        else
                        {
                            // *
                            // *                 ==== Got NS/2 or fewer shifts? Use DLAQR4 or
                            // *                 .    DLAHQR on a trailing principal submatrix to
                            // *                 .    get more. (Since NS.LE.NSMAX.LE.(N+6)/9,
                            // *                 .    there is enough space below the subdiagonal
                            // *                 .    to fit an NS-by-NS scratch array.) ====
                            // *
                            if (KBOT - KS + 1 <= NS / 2)
                            {
                                KS = KBOT - NS + 1;
                                KT = N - NS + 1;
                                this._dlacpy.Run("A", NS, NS, H, KS + KS * LDH + o_h, LDH, ref H, KT + 1 * LDH + o_h
                                                 , LDH);
                                if (NS > NMIN)
                                {
                                    this._dlaqr4.Run(false, false, NS, 1, NS, ref H, KT + 1 * LDH + o_h
                                                     , LDH, ref WR, KS + o_wr, ref WI, KS + o_wi, 1, 1, ref ZDUM, offset_zdum
                                                     , 1, ref WORK, offset_work, LWORK, ref INF);
                                }
                                else
                                {
                                    this._dlahqr.Run(false, false, NS, 1, NS, ref H, KT + 1 * LDH + o_h
                                                     , LDH, ref WR, KS + o_wr, ref WI, KS + o_wi, 1, 1, ref ZDUM, offset_zdum
                                                     , 1, ref INF);
                                }
                                KS += INF;
                                // *
                                // *                    ==== In case of a rare QR failure use
                                // *                    .    eigenvalues of the trailing 2-by-2
                                // *                    .    principal submatrix.  ====
                                // *
                                if (KS >= KBOT)
                                {
                                    AA = H[KBOT - 1 + (KBOT - 1) * LDH + o_h];
                                    CC = H[KBOT + (KBOT - 1) * LDH + o_h];
                                    BB = H[KBOT - 1 + KBOT * LDH + o_h];
                                    DD = H[KBOT + KBOT * LDH + o_h];
                                    this._dlanv2.Run(ref AA, ref BB, ref CC, ref DD, ref WR[KBOT - 1 + o_wr], ref WI[KBOT - 1 + o_wi]
                                                     , ref WR[KBOT + o_wr], ref WI[KBOT + o_wi], ref CS, ref SN);
                                    KS = KBOT - 1;
                                }
                            }
                            // *
                            if (KBOT - KS + 1 > NS)
                            {
                                // *
                                // *                    ==== Sort the shifts (Helps a little)
                                // *                    .    Bubble sort keeps complex conjugate
                                // *                    .    pairs together. ====
                                // *
                                SORTED = false;
                                for (K = KBOT; K >= KS + 1; K += -1)
                                {
                                    if (SORTED)
                                    {
                                        goto LABEL60;
                                    }
                                    SORTED = true;
                                    for (I = KS; I <= K - 1; I++)
                                    {
                                        if (Math.Abs(WR[I + o_wr]) + Math.Abs(WI[I + o_wi]) < Math.Abs(WR[I + 1 + o_wr]) + Math.Abs(WI[I + 1 + o_wi]))
                                        {
                                            SORTED = false;
                                            // *
                                            SWAP             = WR[I + o_wr];
                                            WR[I + o_wr]     = WR[I + 1 + o_wr];
                                            WR[I + 1 + o_wr] = SWAP;
                                            // *
                                            SWAP             = WI[I + o_wi];
                                            WI[I + o_wi]     = WI[I + 1 + o_wi];
                                            WI[I + 1 + o_wi] = SWAP;
                                        }
                                    }
                                }
                                LABEL60 :;
                            }
                            // *
                            // *                 ==== Shuffle shifts into pairs of real shifts
                            // *                 .    and pairs of complex conjugate shifts
                            // *                 .    assuming complex conjugate shifts are
                            // *                 .    already adjacent to one another. (Yes,
                            // *                 .    they are.)  ====
                            // *
                            for (I = KBOT; I >= KS + 2; I += -2)
                            {
                                if (WI[I + o_wi] != -WI[I - 1 + o_wi])
                                {
                                    // *
                                    SWAP             = WR[I + o_wr];
                                    WR[I + o_wr]     = WR[I - 1 + o_wr];
                                    WR[I - 1 + o_wr] = WR[I - 2 + o_wr];
                                    WR[I - 2 + o_wr] = SWAP;
                                    // *
                                    SWAP             = WI[I + o_wi];
                                    WI[I + o_wi]     = WI[I - 1 + o_wi];
                                    WI[I - 1 + o_wi] = WI[I - 2 + o_wi];
                                    WI[I - 2 + o_wi] = SWAP;
                                }
                            }
                        }
                        // *
                        // *              ==== If there are only two shifts and both are
                        // *              .    real, then use only one.  ====
                        // *
                        if (KBOT - KS + 1 == 2)
                        {
                            if (WI[KBOT + o_wi] == ZERO)
                            {
                                if (Math.Abs(WR[KBOT + o_wr] - H[KBOT + KBOT * LDH + o_h]) < Math.Abs(WR[KBOT - 1 + o_wr] - H[KBOT + KBOT * LDH + o_h]))
                                {
                                    WR[KBOT - 1 + o_wr] = WR[KBOT + o_wr];
                                }
                                else
                                {
                                    WR[KBOT + o_wr] = WR[KBOT - 1 + o_wr];
                                }
                            }
                        }
                        // *
                        // *              ==== Use up to NS of the the smallest magnatiude
                        // *              .    shifts.  If there aren't NS shifts available,
                        // *              .    then use them all, possibly dropping one to
                        // *              .    make the number of shifts even. ====
                        // *
                        NS  = Math.Min(NS, KBOT - KS + 1);
                        NS -= FortranLib.Mod(NS, 2);
                        KS  = KBOT - NS + 1;
                        // *
                        // *              ==== Small-bulge multi-shift QR sweep:
                        // *              .    split workspace under the subdiagonal into
                        // *              .    - a KDU-by-KDU work array U in the lower
                        // *              .      left-hand-corner,
                        // *              .    - a KDU-by-at-least-KDU-but-more-is-better
                        // *              .      (KDU-by-NHo) horizontal work array WH along
                        // *              .      the bottom edge,
                        // *              .    - and an at-least-KDU-but-more-is-better-by-KDU
                        // *              .      (NVE-by-KDU) vertical work WV arrow along
                        // *              .      the left-hand-edge. ====
                        // *
                        KDU = 3 * NS - 3;
                        KU  = N - KDU + 1;
                        KWH = KDU + 1;
                        NHO = (N - KDU + 1 - 4) - (KDU + 1) + 1;
                        KWV = KDU + 4;
                        NVE = N - KDU - KWV + 1;
                        // *
                        // *              ==== Small-bulge multi-shift QR sweep ====
                        // *
                        this._dlaqr5.Run(WANTT, WANTZ, KACC22, N, KTOP, KBOT
                                         , NS, ref WR, KS + o_wr, ref WI, KS + o_wi, ref H, offset_h, LDH, ILOZ
                                         , IHIZ, ref Z, offset_z, LDZ, ref WORK, offset_work, 3, ref H, KU + 1 * LDH + o_h
                                         , LDH, NVE, ref H, KWV + 1 * LDH + o_h, LDH, NHO, ref H, KU + KWH * LDH + o_h
                                         , LDH);
                    }
                    // *
                    // *           ==== Note progress (or the lack of it). ====
                    // *
                    if (LD > 0)
                    {
                        NDFL = 1;
                    }
                    else
                    {
                        NDFL += 1;
                    }
                    // *
                    // *           ==== End of main loop ====
                }
                // *
                // *        ==== Iteration limit exceeded.  Set INFO to show where
                // *        .    the problem occurred and exit. ====
                // *
                INFO = KBOT;
                LABEL90 :;
            }
            // *
            // *     ==== Return the optimal value of LWORK. ====
            // *
            WORK[1 + o_work] = Convert.ToDouble(LWKOPT);
            // *
            // *     ==== End of DLAQR0 ====
            // *

            #endregion
        }
Example #5
0
        public void Run(int N, int M, double[] X, int offset_x, double[] G, int offset_g, double[] WS, int offset_ws, double[] WY, int offset_wy
                        , double[] SY, int offset_sy, double[] WT, int offset_wt, double[] Z, int offset_z, ref double[] R, int offset_r, ref double[] WA, int offset_wa, int[] INDEX, int offset_index
                        , double THETA, int COL, int HEAD, int NFREE, bool CNSTND, ref int INFO)
        {
            #region Variables

            int I = 0; int J = 0; int K = 0; int POINTR = 0; double A1 = 0; double A2 = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;  int o_g = -1 + offset_g;  int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;
            int o_sy = -1 - M + offset_sy; int o_wt = -1 - M + offset_wt;  int o_z = -1 + offset_z;  int o_r = -1 + offset_r;
            int o_wa = -1 + offset_wa; int o_index = -1 + offset_index;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine cmprlb
            // c
            // c       This subroutine computes r=-Z'B(xcp-xk)-Z'g by using
            // c         wa(2m+1)=W'(xcp-x) from subroutine cauchy.
            // c
            // c     Subprograms called:
            // c
            // c       L-BFGS-B Library ... bmv.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            #endregion


            #region Body

            if (!CNSTND && COL > 0)
            {
                for (I = 1; I <= N; I++)
                {
                    R[I + o_r] = -G[I + o_g];
                }
            }
            else
            {
                for (I = 1; I <= NFREE; I++)
                {
                    K          = INDEX[I + o_index];
                    R[I + o_r] = -THETA * (Z[K + o_z] - X[K + o_x]) - G[K + o_g];
                }
                this._bmv.Run(M, SY, offset_sy, WT, offset_wt, COL, WA, 2 * M + 1 + o_wa, ref WA, 1 + o_wa
                              , ref INFO);
                if (INFO != 0)
                {
                    INFO = -8;
                    return;
                }
                POINTR = HEAD;
                for (J = 1; J <= COL; J++)
                {
                    A1 = WA[J + o_wa];
                    A2 = THETA * WA[COL + J + o_wa];
                    for (I = 1; I <= NFREE; I++)
                    {
                        K           = INDEX[I + o_index];
                        R[I + o_r] += WY[K + POINTR * N + o_wy] * A1 + WS[K + POINTR * N + o_ws] * A2;
                    }
                    POINTR = FortranLib.Mod(POINTR, M) + 1;
                }
            }

            return;


            #endregion
        }
Example #6
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// takes the sum of the absolute values.
        /// jack dongarra, linpack, 3/11/78.
        /// modified 3/93 to return if incx .le. 0.
        /// modified 12/3/93, array(1) declarations changed to array(*)
        ///</summary>
        public double Run(int N, double[] DX, int offset_dx, int INCX)
        {
            double dasum = 0;

            #region Variables

            double DTEMP = 0; int I = 0; int M = 0; int MP1 = 0; int NINCX = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;

            #endregion


            #region Prolog

            // *     .. Scalar Arguments ..
            // *     ..
            // *     .. Array Arguments ..
            // *     ..
            // *
            // *  Purpose
            // *  =======
            // *
            // *     takes the sum of the absolute values.
            // *     jack dongarra, linpack, 3/11/78.
            // *     modified 3/93 to return if incx .le. 0.
            // *     modified 12/3/93, array(1) declarations changed to array(*)
            // *
            // *
            // *     .. Local Scalars ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC DABS,MOD;
            // *     ..

            #endregion


            #region Body

            dasum = 0.0E0;
            DTEMP = 0.0E0;
            if (N <= 0 || INCX <= 0)
            {
                return(dasum);
            }
            if (INCX == 1)
            {
                goto LABEL20;
            }
            // *
            // *        code for increment not equal to 1
            // *
            NINCX = N * INCX;
            for (I = 1; (INCX >= 0) ? (I <= NINCX) : (I >= NINCX); I += INCX)
            {
                DTEMP += Math.Abs(DX[I + o_dx]);
            }
            dasum = DTEMP;
            return(dasum);

            // *
            // *        code for increment equal to 1
            // *
            // *
            // *        clean-up loop
            // *
            LABEL20 :  M = FortranLib.Mod(N, 6);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DTEMP += Math.Abs(DX[I + o_dx]);
            }
            if (N < 6)
            {
                goto LABEL60;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 6)
            {
                DTEMP += Math.Abs(DX[I + o_dx]) + Math.Abs(DX[I + 1 + o_dx]) + Math.Abs(DX[I + 2 + o_dx]) + Math.Abs(DX[I + 3 + o_dx]) + Math.Abs(DX[I + 4 + o_dx]) + Math.Abs(DX[I + 5 + o_dx]);
            }
            LABEL60 :  dasum = DTEMP;
            return(dasum);

            #endregion
        }
Example #7
0
        public void Run(int N, double[] DX, int offset_dx, int INCX, ref double[] DY, int offset_dy, int INCY)
        {
            #region Variables

            int I = 0; int IX = 0; int IY = 0; int M = 0; int MP1 = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;  int o_dy = -1 + offset_dy;

            #endregion

            // c
            // c     copies a vector, x, to a vector, y.
            // c     uses unrolled loops for increments equal to one.
            // c     jack dongarra, linpack, 3/11/78.
            // c     modified 12/3/93, array(1) declarations changed to array(*)
            // c
            // c

            #region Body

            if (N <= 0)
            {
                return;
            }
            if (INCX == 1 && INCY == 1)
            {
                goto LABEL20;
            }
            // c
            // c        code for unequal increments or equal increments
            // c          not equal to 1
            // c
            IX = 1;
            IY = 1;
            if (INCX < 0)
            {
                IX = (-N + 1) * INCX + 1;
            }
            if (INCY < 0)
            {
                IY = (-N + 1) * INCY + 1;
            }
            for (I = 1; I <= N; I++)
            {
                DY[IY + o_dy] = DX[IX + o_dx];
                IX           += INCX;
                IY           += INCY;
            }
            return;

            // c
            // c        code for both increments equal to 1
            // c
            // c
            // c        clean-up loop
            // c
            LABEL20 :  M = FortranLib.Mod(N, 7);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DY[I + o_dy] = DX[I + o_dx];
            }
            if (N < 7)
            {
                return;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 7)
            {
                DY[I + o_dy]     = DX[I + o_dx];
                DY[I + 1 + o_dy] = DX[I + 1 + o_dx];
                DY[I + 2 + o_dy] = DX[I + 2 + o_dx];
                DY[I + 3 + o_dy] = DX[I + 3 + o_dx];
                DY[I + 4 + o_dy] = DX[I + 4 + o_dx];
                DY[I + 5 + o_dy] = DX[I + 5 + o_dx];
                DY[I + 6 + o_dy] = DX[I + 6 + o_dx];
            }
            return;

            #endregion
        }
Example #8
0
        /// <summary>
        /// Purpose
        /// =======
        /// *
        /// scales a vector by a constant.
        /// uses unrolled loops for increment equal to one.
        /// jack dongarra, linpack, 3/11/78.
        /// modified 3/93 to return if incx .le. 0.
        /// modified 12/3/93, array(1) declarations changed to array(*)
        ///</summary>
        public void Run(int N, double DA, ref double[] DX, int offset_dx, int INCX)
        {
            #region Variables

            int I = 0; int M = 0; int MP1 = 0; int NINCX = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;

            #endregion


            #region Prolog

            // *     .. Scalar Arguments ..
            // *     ..
            // *     .. Array Arguments ..
            // *     ..
            // *
            // *  Purpose
            // *  =======
            // **
            // *     scales a vector by a constant.
            // *     uses unrolled loops for increment equal to one.
            // *     jack dongarra, linpack, 3/11/78.
            // *     modified 3/93 to return if incx .le. 0.
            // *     modified 12/3/93, array(1) declarations changed to array(*)
            // *
            // *
            // *     .. Local Scalars ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC MOD;
            // *     ..

            #endregion


            #region Body

            if (N <= 0 || INCX <= 0)
            {
                return;
            }
            if (INCX == 1)
            {
                goto LABEL20;
            }
            // *
            // *        code for increment not equal to 1
            // *
            NINCX = N * INCX;
            for (I = 1; (INCX >= 0) ? (I <= NINCX) : (I >= NINCX); I += INCX)
            {
                DX[I + o_dx] *= DA;
            }
            return;

            // *
            // *        code for increment equal to 1
            // *
            // *
            // *        clean-up loop
            // *
            LABEL20 :  M = FortranLib.Mod(N, 5);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DX[I + o_dx] *= DA;
            }
            if (N < 5)
            {
                return;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 5)
            {
                DX[I + o_dx]     *= DA;
                DX[I + 1 + o_dx] *= DA;
                DX[I + 2 + o_dx] *= DA;
                DX[I + 3 + o_dx] *= DA;
                DX[I + 4 + o_dx] *= DA;
            }
            return;

            #endregion
        }
Example #9
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="NSUB">
        /// is an integer variable.
        /// On entry nsub is the number of free variables.
        /// On exit nsub is unchanged.
        ///</param>
        /// <param name="IND">
        /// is an integer array of dimension nsub.
        /// On entry ind specifies the coordinate indices of free variables.
        /// On exit ind is unchanged.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound of x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound of x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is a integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds, and
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x specifies the Cauchy point xcp.
        /// On exit x(i) is the minimizer of Q over the subspace of
        /// free variables.
        ///</param>
        /// <param name="D">
        /// = -(Z'BZ)^(-1) r.
        ///
        /// The formula for the Newton direction, given the L-BFGS matrix
        /// and the Sherman-Morrison formula, is
        ///
        /// d = (1/theta)r + (1/theta*2) Z'WK^(-1)W'Z r.
        ///
        /// where
        /// K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        ///
        /// Note that this procedure for computing d differs
        /// from that described in [1]. One can show that the matrix K is
        /// equal to the matrix M^[-1]N in that paper.
        ///
        /// n is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///
        /// m is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///
        /// nsub is an integer variable.
        /// On entry nsub is the number of free variables.
        /// On exit nsub is unchanged.
        ///
        /// ind is an integer array of dimension nsub.
        /// On entry ind specifies the coordinate indices of free variables.
        /// On exit ind is unchanged.
        ///
        /// l is a double precision array of dimension n.
        /// On entry l is the lower bound of x.
        /// On exit l is unchanged.
        ///
        /// u is a double precision array of dimension n.
        /// On entry u is the upper bound of x.
        /// On exit u is unchanged.
        ///
        /// nbd is a integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds, and
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///
        /// x is a double precision array of dimension n.
        /// On entry x specifies the Cauchy point xcp.
        /// On exit x(i) is the minimizer of Q over the subspace of
        /// free variables.
        ///
        /// d is a double precision array of dimension n.
        /// On entry d is the reduced gradient of Q at xcp.
        /// On exit d is the Newton direction of Q.
        ///
        /// ws and wy are double precision arrays;
        /// theta is a double precision variable;
        /// col is an integer variable;
        /// head is an integer variable.
        /// On entry they store the information defining the
        /// limited memory BFGS matrix:
        /// ws(n,m) stores S, a set of s-vectors;
        /// wy(n,m) stores Y, a set of y-vectors;
        /// theta is the scaling factor specifying B_0 = theta I;
        /// col is the number of variable metric corrections stored;
        /// head is the location of the 1st s- (or y-) vector in S (or Y).
        /// On exit they are unchanged.
        ///
        /// iword is an integer variable.
        /// On entry iword is unspecified.
        /// On exit iword specifies the status of the subspace solution.
        /// iword = 0 if the solution is in the box,
        /// 1 if some bound is encountered.
        ///
        /// wv is a double precision working array of dimension 2m.
        ///
        /// wn is a double precision array of dimension 2m x 2m.
        /// On entry the upper triangle of wn stores the LEL^T factorization
        /// of the indefinite matrix
        ///
        /// K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        /// where E = [-I  0]
        /// [ 0  I]
        /// On exit wn is unchanged.
        ///
        /// iprint is an INTEGER variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///
        /// info is an integer variable.
        /// On entry info is unspecified.
        /// On exit info = 0       for normal return,
        /// = nonzero for abnormal return
        /// when the matrix K is ill-conditioned.
        ///
        /// Subprograms called:
        ///
        /// Linpack dtrsl.
        ///
        ///
        /// References:
        ///
        /// [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
        /// memory algorithm for bound constrained optimization'',
        /// SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
        ///
        ///
        ///
        /// *  *  *
        ///
        /// NEOS, November 1994. (Latest revision June 1996.)
        /// Optimization Technology Center.
        /// Argonne National Laboratory and Northwestern University.
        /// Written by
        /// Ciyou Zhu
        /// in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
        ///
        ///
        /// ************
        ///
        ///
        ///
        ///
        ///
        ///</param>
        /// <param name="WS">
        /// and wy are double precision arrays;
        ///</param>
        /// <param name="THETA">
        /// is a double precision variable;
        ///</param>
        /// <param name="COL">
        /// is an integer variable;
        ///</param>
        /// <param name="HEAD">
        /// is an integer variable.
        /// On entry they store the information defining the
        /// limited memory BFGS matrix:
        /// ws(n,m) stores S, a set of s-vectors;
        /// wy(n,m) stores Y, a set of y-vectors;
        /// theta is the scaling factor specifying B_0 = theta I;
        /// col is the number of variable metric corrections stored;
        /// head is the location of the 1st s- (or y-) vector in S (or Y).
        /// On exit they are unchanged.
        ///</param>
        /// <param name="IWORD">
        /// is an integer variable.
        /// On entry iword is unspecified.
        /// On exit iword specifies the status of the subspace solution.
        /// iword = 0 if the solution is in the box,
        /// 1 if some bound is encountered.
        ///</param>
        /// <param name="WV">
        /// is a double precision working array of dimension 2m.
        ///</param>
        /// <param name="WN">
        /// is a double precision array of dimension 2m x 2m.
        /// On entry the upper triangle of wn stores the LEL^T factorization
        /// of the indefinite matrix
        ///
        /// K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        /// where E = [-I  0]
        /// [ 0  I]
        /// On exit wn is unchanged.
        ///</param>
        /// <param name="IPRINT">
        /// is an INTEGER variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="INFO">
        /// is an integer variable.
        /// On entry info is unspecified.
        /// On exit info = 0       for normal return,
        /// = nonzero for abnormal return
        /// when the matrix K is ill-conditioned.
        ///</param>
        public void Run(int N, int M, int NSUB, int[] IND, int offset_ind, double[] L, int offset_l, double[] U, int offset_u
                        , int[] NBD, int offset_nbd, ref double[] X, int offset_x, ref double[] D, int offset_d, double[] WS, int offset_ws, double[] WY, int offset_wy, double THETA
                        , int COL, int HEAD, ref int IWORD, ref double[] WV, int offset_wv, double[] WN, int offset_wn, int IPRINT
                        , ref int INFO)
        {
            #region Variables

            int    POINTR = 0; int M2 = 0; int COL2 = 0; int IBD = 0; int JY = 0; int JS = 0; int I = 0; int J = 0; int K = 0;
            double ALPHA = 0; double DK = 0; double TEMP1 = 0; double TEMP2 = 0;

            #endregion


            #region Array Index Correction

            int o_ind = -1 + offset_ind;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
            int o_x = -1 + offset_x; int o_d = -1 + offset_d;  int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;
            int o_wv = -1 + offset_wv; int o_wn = -1 - (2 * M) + offset_wn;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine subsm
            // c
            // c     Given xcp, l, u, r, an index set that specifies
            // c	the active set at xcp, and an l-BFGS matrix B
            // c	(in terms of WY, WS, SY, WT, head, col, and theta),
            // c	this subroutine computes an approximate solution
            // c	of the subspace problem
            // c
            // c        (P)   min Q(x) = r'(x-xcp) + 1/2 (x-xcp)' B (x-xcp)
            // c
            // c             subject to l<=x<=u
            // c	            x_i=xcp_i for all i in A(xcp)
            // c
            // c	along the subspace unconstrained Newton direction
            // c
            // c	   d = -(Z'BZ)^(-1) r.
            // c
            // c       The formula for the Newton direction, given the L-BFGS matrix
            // c       and the Sherman-Morrison formula, is
            // c
            // c	   d = (1/theta)r + (1/theta*2) Z'WK^(-1)W'Z r.
            // c
            // c       where
            // c                 K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c
            // c     Note that this procedure for computing d differs
            // c     from that described in [1]. One can show that the matrix K is
            // c     equal to the matrix M^[-1]N in that paper.
            // c
            // c     n is an integer variable.
            // c       On entry n is the dimension of the problem.
            // c       On exit n is unchanged.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric corrections
            // c         used to define the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     nsub is an integer variable.
            // c       On entry nsub is the number of free variables.
            // c       On exit nsub is unchanged.
            // c
            // c     ind is an integer array of dimension nsub.
            // c       On entry ind specifies the coordinate indices of free variables.
            // c       On exit ind is unchanged.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound of x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound of x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is a integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds, and
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x specifies the Cauchy point xcp.
            // c       On exit x(i) is the minimizer of Q over the subspace of
            // c                                                        free variables.
            // c
            // c     d is a double precision array of dimension n.
            // c       On entry d is the reduced gradient of Q at xcp.
            // c       On exit d is the Newton direction of Q.
            // c
            // c     ws and wy are double precision arrays;
            // c     theta is a double precision variable;
            // c     col is an integer variable;
            // c     head is an integer variable.
            // c       On entry they store the information defining the
            // c                                          limited memory BFGS matrix:
            // c         ws(n,m) stores S, a set of s-vectors;
            // c         wy(n,m) stores Y, a set of y-vectors;
            // c         theta is the scaling factor specifying B_0 = theta I;
            // c         col is the number of variable metric corrections stored;
            // c         head is the location of the 1st s- (or y-) vector in S (or Y).
            // c       On exit they are unchanged.
            // c
            // c     iword is an integer variable.
            // c       On entry iword is unspecified.
            // c       On exit iword specifies the status of the subspace solution.
            // c         iword = 0 if the solution is in the box,
            // c                 1 if some bound is encountered.
            // c
            // c     wv is a double precision working array of dimension 2m.
            // c
            // c     wn is a double precision array of dimension 2m x 2m.
            // c       On entry the upper triangle of wn stores the LEL^T factorization
            // c         of the indefinite matrix
            // c
            // c              K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                  [L_a -R_z           theta*S'AA'S ]
            // c                                                    where E = [-I  0]
            // c                                                              [ 0  I]
            // c       On exit wn is unchanged.
            // c
            // c     iprint is an INTEGER variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     info is an integer variable.
            // c       On entry info is unspecified.
            // c       On exit info = 0       for normal return,
            // c                    = nonzero for abnormal return
            // c                                  when the matrix K is ill-conditioned.
            // c
            // c     Subprograms called:
            // c
            // c       Linpack dtrsl.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            #endregion


            #region Body

            if (NSUB <= 0)
            {
                return;
            }
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,1001)
            }
            // c     Compute wv = W'Zd.

            POINTR = HEAD;
            for (I = 1; I <= COL; I++)
            {
                TEMP1 = ZERO;
                TEMP2 = ZERO;
                for (J = 1; J <= NSUB; J++)
                {
                    K      = IND[J + o_ind];
                    TEMP1 += WY[K + POINTR * N + o_wy] * D[J + o_d];
                    TEMP2 += WS[K + POINTR * N + o_ws] * D[J + o_d];
                }
                WV[I + o_wv]       = TEMP1;
                WV[COL + I + o_wv] = THETA * TEMP2;
                POINTR             = FortranLib.Mod(POINTR, M) + 1;
            }

            // c     Compute wv:=K^(-1)wv.

            M2   = 2 * M;
            COL2 = 2 * COL;
            this._dtrsl.Run(WN, offset_wn, M2, COL2, ref WV, offset_wv, 11, ref INFO);
            if (INFO != 0)
            {
                return;
            }
            for (I = 1; I <= COL; I++)
            {
                WV[I + o_wv] = -WV[I + o_wv];
            }
            this._dtrsl.Run(WN, offset_wn, M2, COL2, ref WV, offset_wv, 01, ref INFO);
            if (INFO != 0)
            {
                return;
            }

            // c     Compute d = (1/theta)d + (1/theta**2)Z'W wv.

            POINTR = HEAD;
            for (JY = 1; JY <= COL; JY++)
            {
                JS = COL + JY;
                for (I = 1; I <= NSUB; I++)
                {
                    K           = IND[I + o_ind];
                    D[I + o_d] += WY[K + POINTR * N + o_wy] * WV[JY + o_wv] / THETA + WS[K + POINTR * N + o_ws] * WV[JS + o_wv];
                }
                POINTR = FortranLib.Mod(POINTR, M) + 1;
            }
            for (I = 1; I <= NSUB; I++)
            {
                D[I + o_d] /= THETA;
            }

            // c     Backtrack to the feasible region.

            ALPHA = ONE;
            TEMP1 = ALPHA;
            for (I = 1; I <= NSUB; I++)
            {
                K  = IND[I + o_ind];
                DK = D[I + o_d];
                if (NBD[K + o_nbd] != 0)
                {
                    if (DK < ZERO && NBD[K + o_nbd] <= 2)
                    {
                        TEMP2 = L[K + o_l] - X[K + o_x];
                        if (TEMP2 >= ZERO)
                        {
                            TEMP1 = ZERO;
                        }
                        else
                        {
                            if (DK * ALPHA < TEMP2)
                            {
                                TEMP1 = TEMP2 / DK;
                            }
                        }
                    }
                    else
                    {
                        if (DK > ZERO && NBD[K + o_nbd] >= 2)
                        {
                            TEMP2 = U[K + o_u] - X[K + o_x];
                            if (TEMP2 <= ZERO)
                            {
                                TEMP1 = ZERO;
                            }
                            else
                            {
                                if (DK * ALPHA > TEMP2)
                                {
                                    TEMP1 = TEMP2 / DK;
                                }
                            }
                        }
                    }
                    if (TEMP1 < ALPHA)
                    {
                        ALPHA = TEMP1;
                        IBD   = I;
                    }
                }
            }

            if (ALPHA < ONE)
            {
                DK = D[IBD + o_d];
                K  = IND[IBD + o_ind];
                if (DK > ZERO)
                {
                    X[K + o_x]   = U[K + o_u];
                    D[IBD + o_d] = ZERO;
                }
                else
                {
                    if (DK < ZERO)
                    {
                        X[K + o_x]   = L[K + o_l];
                        D[IBD + o_d] = ZERO;
                    }
                }
            }
            for (I = 1; I <= NSUB; I++)
            {
                K           = IND[I + o_ind];
                X[K + o_x] += ALPHA * D[I + o_d];
            }

            if (IPRINT >= 99)
            {
                if (ALPHA < ONE)
                {
                    //ERROR-ERROR            WRITE (6,1002) ALPHA;
                }
                else
                {
                    //ERROR-ERROR            WRITE (6,*) 'SM solution inside the box';
                }
                if (IPRINT > 100)
                {
                    ;              //ERROR-ERRORWRITE(6,1003)(X(I),I=1,N)
                }
            }

            if (ALPHA < ONE)
            {
                IWORD = 1;
            }
            else
            {
                IWORD = 0;
            }
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,1004)
            }
            return;


            #endregion
        }
Example #10
0
        public void Run(int N, IFAREN FCN, ref double X, ref double[] Y, int offset_y, double XEND, ref double HMAX
                        , ref double H, double[] RTOL, int offset_rtol, double[] ATOL, int offset_atol, int ITOL, int IPRINT, ISOLOUT SOLOUT
                        , int IOUT, ref int IDID, int NMAX, double UROUND, int METH, int NSTIFF
                        , double SAFE, double BETA, double FAC1, double FAC2, ref double[] Y1, int offset_y1, ref double[] K1, int offset_k1
                        , ref double[] K2, int offset_k2, ref double[] K3, int offset_k3, ref double[] K4, int offset_k4, ref double[] K5, int offset_k5, ref double[] K6, int offset_k6, ref double[] YSTI, int offset_ysti
                        , ref double[] CONT, int offset_cont, int[] ICOMP, int offset_icomp, int NRD, double[] RPAR, int offset_rpar, int[] IPAR, int offset_ipar, ref int NFCN
                        , ref int NSTEP, ref int NACCPT, ref int NREJCT)
        {
            #region Variables

            bool REJECT = false; bool LAST = false;
            #endregion
            #region Implicit Variables

            double FACOLD = 0; double EXPO1 = 0; double FACC1 = 0; double FACC2 = 0; double POSNEG = 0; double ATOLI = 0;
            double RTOLI = 0; double HLAMB = 0; int IASTI = 0; int IORD = 0; int IRTRN = 0; int I = 0; double A21 = 0;
            double A31 = 0; double A32 = 0; double A41 = 0; double A42 = 0; double A43 = 0; double A51 = 0; double A52 = 0;
            double A53 = 0; double A54 = 0; double A61 = 0; double A62 = 0; double A63 = 0; double A64 = 0; double A65 = 0;
            double XPH = 0; double A71 = 0; double A73 = 0; double A74 = 0; double A75 = 0; double A76 = 0; int J = 0;
            double D1 = 0; double D3 = 0; double D4 = 0; double D5 = 0; double D6 = 0; double D7 = 0; double E1 = 0; double E3 = 0;
            double E4 = 0; double E5 = 0; double E6 = 0; double E7 = 0; double ERR = 0; double SK = 0; double FAC11 = 0;
            double FAC = 0; double HNEW = 0; double STNUM = 0; double STDEN = 0; int NONSTI = 0; double YD0 = 0; double YDIFF = 0;
            double BSPL = 0; double C2 = 0; double C3 = 0; double C4 = 0; double C5 = 0;
            #endregion
            #region Array Index Correction

            int o_y = -1 + offset_y;  int o_rtol = -1 + offset_rtol;  int o_atol = -1 + offset_atol;  int o_y1 = -1 + offset_y1;
            int o_k1 = -1 + offset_k1; int o_k2 = -1 + offset_k2;  int o_k3 = -1 + offset_k3;  int o_k4 = -1 + offset_k4;
            int o_k5 = -1 + offset_k5; int o_k6 = -1 + offset_k6;  int o_ysti = -1 + offset_ysti;  int o_cont = -1 + offset_cont;
            int o_icomp = -1 + offset_icomp; int o_rpar = -1 + offset_rpar;  int o_ipar = -1 + offset_ipar;
            #endregion
            // C ----------------------------------------------------------
            // C     CORE INTEGRATOR FOR DOPRI5
            // C     PARAMETERS SAME AS IN DOPRI5 WITH WORKSPACE ADDED
            // C ----------------------------------------------------------
            // C         DECLARATIONS
            // C ----------------------------------------------------------
            // C *** *** *** *** *** *** ***
            // C  INITIALISATIONS
            // C *** *** *** *** *** *** ***
            #region Body

            if (METH == 1)
            {
                this._cdopri.Run(ref C2, ref C3, ref C4, ref C5, ref E1, ref E3
                                 , ref E4, ref E5, ref E6, ref E7, ref A21, ref A31
                                 , ref A32, ref A41, ref A42, ref A43, ref A51, ref A52
                                 , ref A53, ref A54, ref A61, ref A62, ref A63, ref A64
                                 , ref A65, ref A71, ref A73, ref A74, ref A75, ref A76
                                 , ref D1, ref D3, ref D4, ref D5, ref D6, ref D7);
            }
            FACOLD = 1.0E-4;
            EXPO1  = 0.2E0 - BETA * 0.75E0;
            FACC1  = 1.0E0 / FAC1;
            FACC2  = 1.0E0 / FAC2;
            POSNEG = FortranLib.Sign(1.0E0, XEND - X);
            // C --- INITIAL PREPARATIONS
            ATOLI = ATOL[1 + o_atol];
            RTOLI = RTOL[1 + o_rtol];
            LAST  = false;
            HLAMB = 0.0E0;
            IASTI = 0;
            FCN.Run(N, X, Y, offset_y, ref K1, offset_k1, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            HMAX = Math.Abs(HMAX);
            IORD = 5;
            if (H == 0.0E0)
            {
                H = this._hinit.Run(N, FCN, X, Y, offset_y, XEND, POSNEG, K1, offset_k1, ref K2, offset_k2, ref K3, offset_k3, IORD, HMAX, ATOL, offset_atol, RTOL, offset_rtol, ITOL, RPAR, offset_rpar, IPAR, offset_ipar);
            }
            NFCN  += 2;
            REJECT = false;
            XOLD.v = X;
            if (IOUT != 0)
            {
                IRTRN  = 1;
                HOUT.v = H;
                SOLOUT.Run(NACCPT + 1, XOLD.v, X, Y, offset_y, N, CONT, offset_cont
                           , ICOMP, offset_icomp, NRD, RPAR, offset_rpar, IPAR[1 + o_ipar], IRTRN);
                if (IRTRN < 0)
                {
                    goto LABEL79;
                }
            }
            else
            {
                IRTRN = 0;
            }
            // C --- BASIC INTEGRATION STEP
            LABEL1 :;
            if (NSTEP > NMAX)
            {
                goto LABEL78;
            }
            if (0.1E0 * Math.Abs(H) <= Math.Abs(X) * UROUND)
            {
                goto LABEL77;
            }
            if ((X + 1.01E0 * H - XEND) * POSNEG > 0.0E0)
            {
                H    = XEND - X;
                LAST = true;
            }
            NSTEP += 1;
            // C --- THE FIRST 6 STAGES
            if (IRTRN >= 2)
            {
                FCN.Run(N, X, Y, offset_y, ref K1, offset_k1, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            }
            for (I = 1; I <= N; I++)
            {
                Y1[I + o_y1] = Y[I + o_y] + H * A21 * K1[I + o_k1];
            }
            FCN.Run(N, X + C2 * H, Y1, offset_y1, ref K2, offset_k2, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            for (I = 1; I <= N; I++)
            {
                Y1[I + o_y1] = Y[I + o_y] + H * (A31 * K1[I + o_k1] + A32 * K2[I + o_k2]);
            }
            FCN.Run(N, X + C3 * H, Y1, offset_y1, ref K3, offset_k3, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            for (I = 1; I <= N; I++)
            {
                Y1[I + o_y1] = Y[I + o_y] + H * (A41 * K1[I + o_k1] + A42 * K2[I + o_k2] + A43 * K3[I + o_k3]);
            }
            FCN.Run(N, X + C4 * H, Y1, offset_y1, ref K4, offset_k4, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            for (I = 1; I <= N; I++)
            {
                Y1[I + o_y1] = Y[I + o_y] + H * (A51 * K1[I + o_k1] + A52 * K2[I + o_k2] + A53 * K3[I + o_k3] + A54 * K4[I + o_k4]);
            }
            FCN.Run(N, X + C5 * H, Y1, offset_y1, ref K5, offset_k5, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            for (I = 1; I <= N; I++)
            {
                YSTI[I + o_ysti] = Y[I + o_y] + H * (A61 * K1[I + o_k1] + A62 * K2[I + o_k2] + A63 * K3[I + o_k3] + A64 * K4[I + o_k4] + A65 * K5[I + o_k5]);
            }
            XPH = X + H;
            FCN.Run(N, XPH, YSTI, offset_ysti, ref K6, offset_k6, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            for (I = 1; I <= N; I++)
            {
                Y1[I + o_y1] = Y[I + o_y] + H * (A71 * K1[I + o_k1] + A73 * K3[I + o_k3] + A74 * K4[I + o_k4] + A75 * K5[I + o_k5] + A76 * K6[I + o_k6]);
            }
            FCN.Run(N, XPH, Y1, offset_y1, ref K2, offset_k2, RPAR, offset_rpar, IPAR[1 + o_ipar]);
            if (IOUT >= 2)
            {
                for (J = 1; J <= NRD; J++)
                {
                    I = ICOMP[J + o_icomp];
                    CONT[4 * NRD + J + o_cont] = H * (D1 * K1[I + o_k1] + D3 * K3[I + o_k3] + D4 * K4[I + o_k4] + D5 * K5[I + o_k5] + D6 * K6[I + o_k6] + D7 * K2[I + o_k2]);
                }
            }
            for (I = 1; I <= N; I++)
            {
                K4[I + o_k4] = (E1 * K1[I + o_k1] + E3 * K3[I + o_k3] + E4 * K4[I + o_k4] + E5 * K5[I + o_k5] + E6 * K6[I + o_k6] + E7 * K2[I + o_k2]) * H;
            }
            NFCN += 6;
            // C --- ERROR ESTIMATION
            ERR = 0.0E0;
            if (ITOL == 0)
            {
                for (I = 1; I <= N; I++)
                {
                    SK   = ATOLI + RTOLI * Math.Max(Math.Abs(Y[I + o_y]), Math.Abs(Y1[I + o_y1]));
                    ERR += Math.Pow(K4[I + o_k4] / SK, 2);
                }
            }
            else
            {
                for (I = 1; I <= N; I++)
                {
                    SK   = ATOL[I + o_atol] + RTOL[I + o_rtol] * Math.Max(Math.Abs(Y[I + o_y]), Math.Abs(Y1[I + o_y1]));
                    ERR += Math.Pow(K4[I + o_k4] / SK, 2);
                }
            }
            ERR = Math.Sqrt(ERR / N);
            // C --- COMPUTATION OF HNEW
            FAC11 = Math.Pow(ERR, EXPO1);
            // C --- LUND-STABILIZATION
            FAC = FAC11 / Math.Pow(FACOLD, BETA);
            // C --- WE REQUIRE  FAC1 <= HNEW/H <= FAC2
            FAC  = Math.Max(FACC2, Math.Min(FACC1, FAC / SAFE));
            HNEW = H / FAC;
            if (ERR <= 1.0E0)
            {
                // C --- STEP IS ACCEPTED
                FACOLD  = Math.Max(ERR, 1.0E-4);
                NACCPT += 1;
                // C ------- STIFFNESS DETECTION
                if (FortranLib.Mod(NACCPT, NSTIFF) == 0 || IASTI > 0)
                {
                    STNUM = 0.0E0;
                    STDEN = 0.0E0;
                    for (I = 1; I <= N; I++)
                    {
                        STNUM += Math.Pow(K2[I + o_k2] - K6[I + o_k6], 2);
                        STDEN += Math.Pow(Y1[I + o_y1] - YSTI[I + o_ysti], 2);
                    }
                    if (STDEN > 0.0E0)
                    {
                        HLAMB = H * Math.Sqrt(STNUM / STDEN);
                    }
                    if (HLAMB > 3.25E0)
                    {
                        NONSTI = 0;
                        IASTI += 1;
                        if (IASTI == 15)
                        {
                            if (IPRINT > 0)
                            {
                                ;            //ERROR-ERRORWRITE(IPRINT,*)' THE PROBLEM SEEMS TO BECOME STIFF AT X = ',X
                            }
                            if (IPRINT <= 0)
                            {
                                goto LABEL76;
                            }
                        }
                    }
                    else
                    {
                        NONSTI += 1;
                        if (NONSTI == 6)
                        {
                            IASTI = 0;
                        }
                    }
                }
                if (IOUT >= 2)
                {
                    for (J = 1; J <= NRD; J++)
                    {
                        I                          = ICOMP[J + o_icomp];
                        YD0                        = Y[I + o_y];
                        YDIFF                      = Y1[I + o_y1] - YD0;
                        BSPL                       = H * K1[I + o_k1] - YDIFF;
                        CONT[J + o_cont]           = Y[I + o_y];
                        CONT[NRD + J + o_cont]     = YDIFF;
                        CONT[2 * NRD + J + o_cont] = BSPL;
                        CONT[3 * NRD + J + o_cont] = -H * K2[I + o_k2] + YDIFF - BSPL;
                    }
                }
                for (I = 1; I <= N; I++)
                {
                    K1[I + o_k1] = K2[I + o_k2];
                    Y[I + o_y]   = Y1[I + o_y1];
                }
                XOLD.v = X;
                X      = XPH;
                if (IOUT != 0)
                {
                    HOUT.v = H;
                    SOLOUT.Run(NACCPT + 1, XOLD.v, X, Y, offset_y, N, CONT, offset_cont
                               , ICOMP, offset_icomp, NRD, RPAR, offset_rpar, IPAR[1 + o_ipar], IRTRN);
                    if (IRTRN < 0)
                    {
                        goto LABEL79;
                    }
                }
                // C ------- NORMAL EXIT
                if (LAST)
                {
                    H    = HNEW;
                    IDID = 1;
                    return;
                }
                if (Math.Abs(HNEW) > HMAX)
                {
                    HNEW = POSNEG * HMAX;
                }
                if (REJECT)
                {
                    HNEW = POSNEG * Math.Min(Math.Abs(HNEW), Math.Abs(H));
                }
                REJECT = false;
            }
            else
            {
                // C --- STEP IS REJECTED
                HNEW   = H / Math.Min(FACC1, FAC11 / SAFE);
                REJECT = true;
                if (NACCPT >= 1)
                {
                    NREJCT += 1;
                }
                LAST = false;
            }
            H = HNEW;
            goto LABEL1;
            // C --- FAIL EXIT
            LABEL76 :;
            IDID = -4;
            return;

            LABEL77 :;
            if (IPRINT > 0)
            {
                ;            //ERROR-ERRORWRITE(IPRINT,979)X
            }
            if (IPRINT > 0)
            {
                ;            //ERROR-ERRORWRITE(IPRINT,*)' STEP SIZE T0O SMALL, H=',H
            }
            IDID = -3;
            return;

            LABEL78 :;
            if (IPRINT > 0)
            {
                ;            //ERROR-ERRORWRITE(IPRINT,979)X
            }
            if (IPRINT > 0)
            {
                ;            //ERROR-ERRORWRITE(IPRINT,*)' MORE THAN NMAX =',NMAX,'STEPS ARE NEEDED'
            }
            IDID = -2;
            return;

            LABEL79 :;
            if (IPRINT > 0)
            {
                ;            //ERROR-ERRORWRITE(IPRINT,979)X
            }
            IDID = 2;
            return;

            #endregion
        }
Example #11
0
        public void Run(int N, double DA, double[] DX, int offset_dx, int INCX, ref double[] DY, int offset_dy, int INCY)
        {
            #region Variables

            int I = 0; int IX = 0; int IY = 0; int M = 0; int MP1 = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;  int o_dy = -1 + offset_dy;

            #endregion

            // c
            // c     constant times a vector plus a vector.
            // c     uses unrolled loops for increments equal to one.
            // c     jack dongarra, linpack, 3/11/78.
            // c
            // c

            #region Body

            if (N <= 0)
            {
                return;
            }
            if (DA == 0.0E0)
            {
                return;
            }
            if (INCX == 1 && INCY == 1)
            {
                goto LABEL20;
            }
            // c
            // c        code for unequal increments or equal increments
            // c          not equal to 1
            // c
            IX = 1;
            IY = 1;
            if (INCX < 0)
            {
                IX = (-N + 1) * INCX + 1;
            }
            if (INCY < 0)
            {
                IY = (-N + 1) * INCY + 1;
            }
            for (I = 1; I <= N; I++)
            {
                DY[IY + o_dy] += DA * DX[IX + o_dx];
                IX            += INCX;
                IY            += INCY;
            }
            return;

            // c
            // c        code for both increments equal to 1
            // c
            // c
            // c        clean-up loop
            // c
            LABEL20 :  M = FortranLib.Mod(N, 4);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DY[I + o_dy] += DA * DX[I + o_dx];
            }
            if (N < 4)
            {
                return;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 4)
            {
                DY[I + o_dy]     += DA * DX[I + o_dx];
                DY[I + 1 + o_dy] += DA * DX[I + 1 + o_dx];
                DY[I + 2 + o_dy] += DA * DX[I + 2 + o_dx];
                DY[I + 3 + o_dy] += DA * DX[I + 3 + o_dx];
            }
            return;

            #endregion
        }
Example #12
0
        /// <param name="T">
        /// * x = b
        ///</param>
        /// <param name="LDT">
        /// integer
        /// ldt is the leading dimension of the array t.
        ///</param>
        /// <param name="N">
        /// integer
        /// n is the order of the system.
        ///</param>
        /// <param name="B">
        /// double precision(n).
        /// b contains the right hand side of the system.
        ///</param>
        /// <param name="JOB">
        /// integer
        /// job specifies what kind of system is to be solved.
        /// if job is
        ///
        /// 00   solve t*x=b, t lower triangular,
        /// 01   solve t*x=b, t upper triangular,
        /// 10   solve trans(t)*x=b, t lower triangular,
        /// 11   solve trans(t)*x=b, t upper triangular.
        ///</param>
        /// <param name="INFO">
        /// integer
        /// info contains zero if the system is nonsingular.
        /// otherwise info contains the index of
        /// the first zero diagonal element of t.
        ///</param>
        public void Run(double[] T, int offset_t, int LDT, int N, ref double[] B, int offset_b, int JOB, ref int INFO)
        {
            #region Variables

            double TEMP = 0; int CASE = 0; int J = 0; int JJ = 0;

            #endregion


            #region Array Index Correction

            int o_t = -1 - LDT + offset_t;  int o_b = -1 + offset_b;

            #endregion


            #region Prolog

            // c
            // c
            // c     dtrsl solves systems of the form
            // c
            // c                   t * x = b
            // c     or
            // c                   trans(t) * x = b
            // c
            // c     where t is a triangular matrix of order n. here trans(t)
            // c     denotes the transpose of the matrix t.
            // c
            // c     on entry
            // c
            // c         t         double precision(ldt,n)
            // c                   t contains the matrix of the system. the zero
            // c                   elements of the matrix are not referenced, and
            // c                   the corresponding elements of the array can be
            // c                   used to store other information.
            // c
            // c         ldt       integer
            // c                   ldt is the leading dimension of the array t.
            // c
            // c         n         integer
            // c                   n is the order of the system.
            // c
            // c         b         double precision(n).
            // c                   b contains the right hand side of the system.
            // c
            // c         job       integer
            // c                   job specifies what kind of system is to be solved.
            // c                   if job is
            // c
            // c                        00   solve t*x=b, t lower triangular,
            // c                        01   solve t*x=b, t upper triangular,
            // c                        10   solve trans(t)*x=b, t lower triangular,
            // c                        11   solve trans(t)*x=b, t upper triangular.
            // c
            // c     on return
            // c
            // c         b         b contains the solution, if info .eq. 0.
            // c                   otherwise b is unaltered.
            // c
            // c         info      integer
            // c                   info contains zero if the system is nonsingular.
            // c                   otherwise info contains the index of
            // c                   the first zero diagonal element of t.
            // c
            // c     linpack. this version dated 08/14/78 .
            // c     g. w. stewart, university of maryland, argonne national lab.
            // c
            // c     subroutines and functions
            // c
            // c     blas daxpy,ddot
            // c     fortran mod
            // c
            // c     internal variables
            // c
            //	INTRINSIC MOD;
            // c
            // c     begin block permitting ...exits to 150
            // c
            // c        check for zero diagonal elements.
            // c

            #endregion


            #region Body

            for (INFO = 1; INFO <= N; INFO++)
            {
                // c     ......exit
                if (T[INFO + INFO * LDT + o_t] == 0.0E0)
                {
                    goto LABEL150;
                }
            }
            INFO = 0;
            // c
            // c        determine the task and go to it.
            // c
            CASE = 1;
            if (FortranLib.Mod(JOB, 10) != 0)
            {
                CASE = 2;
            }
            if (FortranLib.Mod(JOB, 100) / 10 != 0)
            {
                CASE += 2;
            }
            switch (CASE)
            {
            case 1: goto LABEL20;

            case 2: goto LABEL50;

            case 3: goto LABEL80;

            case 4: goto LABEL110;
            }
            // c
            // c        solve t*x=b for t lower triangular
            // c
            LABEL20 :;
            B[1 + o_b] /= T[1 + 1 * LDT + o_t];
            if (N < 2)
            {
                goto LABEL40;
            }
            for (J = 2; J <= N; J++)
            {
                TEMP = -B[J - 1 + o_b];
                this._daxpy.Run(N - J + 1, TEMP, T, J + (J - 1) * LDT + o_t, 1, ref B, J + o_b, 1);
                B[J + o_b] /= T[J + J * LDT + o_t];
            }
            LABEL40 :;
            goto LABEL140;
            // c
            // c        solve t*x=b for t upper triangular.
            // c
            LABEL50 :;
            B[N + o_b] /= T[N + N * LDT + o_t];
            if (N < 2)
            {
                goto LABEL70;
            }
            for (JJ = 2; JJ <= N; JJ++)
            {
                J    = N - JJ + 1;
                TEMP = -B[J + 1 + o_b];
                this._daxpy.Run(J, TEMP, T, 1 + (J + 1) * LDT + o_t, 1, ref B, 1 + o_b, 1);
                B[J + o_b] /= T[J + J * LDT + o_t];
            }
            LABEL70 :;
            goto LABEL140;
            // c
            // c        solve trans(t)*x=b for t lower triangular.
            // c
            LABEL80 :;
            B[N + o_b] /= T[N + N * LDT + o_t];
            if (N < 2)
            {
                goto LABEL100;
            }
            for (JJ = 2; JJ <= N; JJ++)
            {
                J           = N - JJ + 1;
                B[J + o_b] -= this._ddot.Run(JJ - 1, T, J + 1 + J * LDT + o_t, 1, B, J + 1 + o_b, 1);
                B[J + o_b] /= T[J + J * LDT + o_t];
            }
            LABEL100 :;
            goto LABEL140;
            // c
            // c        solve trans(t)*x=b for t upper triangular.
            // c
            LABEL110 :;
            B[1 + o_b] /= T[1 + 1 * LDT + o_t];
            if (N < 2)
            {
                goto LABEL130;
            }
            for (J = 2; J <= N; J++)
            {
                B[J + o_b] -= this._ddot.Run(J - 1, T, 1 + J * LDT + o_t, 1, B, 1 + o_b, 1);
                B[J + o_b] /= T[J + J * LDT + o_t];
            }
            LABEL130 :;
            LABEL140 :;
            LABEL150 :;
            return;

            #endregion
        }
Example #13
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="NSUB">
        /// is an integer variable
        /// On entry nsub is the number of subspace variables in free set.
        /// On exit nsub is not changed.
        ///</param>
        /// <param name="IND">
        /// is an integer array of dimension nsub.
        /// On entry ind specifies the indices of subspace variables.
        /// On exit ind is unchanged.
        ///</param>
        /// <param name="NENTER">
        /// is an integer variable.
        /// On entry nenter is the number of variables entering the
        /// free set.
        /// On exit nenter is unchanged.
        ///</param>
        /// <param name="ILEAVE">
        /// is an integer variable.
        /// On entry indx2(ileave),...,indx2(n) are the variables leaving
        /// the free set.
        /// On exit ileave is unchanged.
        ///</param>
        /// <param name="INDX2">
        /// is an integer array of dimension n.
        /// On entry indx2(1),...,indx2(nenter) are the variables entering
        /// the free set, while indx2(ileave),...,indx2(n) are the
        /// variables leaving the free set.
        /// On exit indx2 is unchanged.
        ///</param>
        /// <param name="IUPDAT">
        /// is an integer variable.
        /// On entry iupdat is the total number of BFGS updates made so far.
        /// On exit iupdat is unchanged.
        ///</param>
        /// <param name="UPDATD">
        /// is a logical variable.
        /// On entry 'updatd' is true if the L-BFGS matrix is updatd.
        /// On exit 'updatd' is unchanged.
        ///</param>
        /// <param name="WN">
        /// is a double precision array of dimension 2m x 2m.
        /// On entry wn is unspecified.
        /// On exit the upper triangle of wn stores the LEL^T factorization
        /// of the 2*col x 2*col indefinite matrix
        /// [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        ///</param>
        /// <param name="WN1">
        /// is a double precision array of dimension 2m x 2m.
        /// On entry wn1 stores the lower triangular part of
        /// [Y' ZZ'Y   L_a'+R_z']
        /// [L_a+R_z   S'AA'S   ]
        /// in the previous iteration.
        /// On exit wn1 stores the corresponding updated matrices.
        /// The purpose of wn1 is just to store these inner products
        /// so they can be easily updated and inserted into wn.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="THETA">
        /// is a double precision variable;
        ///</param>
        /// <param name="COL">
        /// is an integer variable;
        ///</param>
        /// <param name="HEAD">
        /// is an integer variable.
        /// On entry they store the information defining the
        /// limited memory BFGS matrix:
        /// ws(n,m) stores S, a set of s-vectors;
        /// wy(n,m) stores Y, a set of y-vectors;
        /// sy(m,m) stores S'Y;
        /// wtyy(m,m) stores the Cholesky factorization
        /// of (theta*S'S+LD^(-1)L')
        /// theta is the scaling factor specifying B_0 = theta I;
        /// col is the number of variable metric corrections stored;
        /// head is the location of the 1st s- (or y-) vector in S (or Y).
        /// On exit they are unchanged.
        ///</param>
        /// <param name="INFO">
        /// is an integer variable.
        /// On entry info is unspecified.
        /// On exit info =  0 for normal return;
        /// = -1 when the 1st Cholesky factorization failed;
        /// = -2 when the 2st Cholesky factorization failed.
        ///</param>
        public void Run(int N, int NSUB, int[] IND, int offset_ind, int NENTER, int ILEAVE, int[] INDX2, int offset_indx2
                        , int IUPDAT, bool UPDATD, ref double[] WN, int offset_wn, ref double[] WN1, int offset_wn1, int M, double[] WS, int offset_ws
                        , double[] WY, int offset_wy, double[] SY, int offset_sy, double THETA, int COL, int HEAD, ref int INFO)
        {
            #region Variables

            int M2 = 0; int IPNTR = 0; int JPNTR = 0; int IY = 0; int IS = 0; int JY = 0; int JS = 0; int IS1 = 0; int JS1 = 0;
            int K1 = 0; int I = 0; int K = 0; int COL2 = 0; int PBEGIN = 0; int PEND = 0; int DBEGIN = 0; int DEND = 0;
            int UPCL = 0; double TEMP1 = 0; double TEMP2 = 0; double TEMP3 = 0; double TEMP4 = 0;

            #endregion


            #region Implicit Variables

            int WN_IY = 0; int WN_IS = 0;

            #endregion


            #region Array Index Correction

            int o_ind = -1 + offset_ind;  int o_indx2 = -1 + offset_indx2;  int o_wn = -1 - (2 * M) + offset_wn;
            int o_wn1 = -1 - (2 * M) + offset_wn1; int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;
            int o_sy = -1 - M + offset_sy;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine formk
            // c
            // c     This subroutine forms  the LEL^T factorization of the indefinite
            // c
            // c       matrix    K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c                                                    where E = [-I  0]
            // c                                                              [ 0  I]
            // c     The matrix K can be shown to be equal to the matrix M^[-1]N
            // c       occurring in section 5.1 of [1], as well as to the matrix
            // c       Mbar^[-1] Nbar in section 5.3.
            // c
            // c     n is an integer variable.
            // c       On entry n is the dimension of the problem.
            // c       On exit n is unchanged.
            // c
            // c     nsub is an integer variable
            // c       On entry nsub is the number of subspace variables in free set.
            // c       On exit nsub is not changed.
            // c
            // c     ind is an integer array of dimension nsub.
            // c       On entry ind specifies the indices of subspace variables.
            // c       On exit ind is unchanged.
            // c
            // c     nenter is an integer variable.
            // c       On entry nenter is the number of variables entering the
            // c         free set.
            // c       On exit nenter is unchanged.
            // c
            // c     ileave is an integer variable.
            // c       On entry indx2(ileave),...,indx2(n) are the variables leaving
            // c         the free set.
            // c       On exit ileave is unchanged.
            // c
            // c     indx2 is an integer array of dimension n.
            // c       On entry indx2(1),...,indx2(nenter) are the variables entering
            // c         the free set, while indx2(ileave),...,indx2(n) are the
            // c         variables leaving the free set.
            // c       On exit indx2 is unchanged.
            // c
            // c     iupdat is an integer variable.
            // c       On entry iupdat is the total number of BFGS updates made so far.
            // c       On exit iupdat is unchanged.
            // c
            // c     updatd is a logical variable.
            // c       On entry 'updatd' is true if the L-BFGS matrix is updatd.
            // c       On exit 'updatd' is unchanged.
            // c
            // c     wn is a double precision array of dimension 2m x 2m.
            // c       On entry wn is unspecified.
            // c       On exit the upper triangle of wn stores the LEL^T factorization
            // c         of the 2*col x 2*col indefinite matrix
            // c                     [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c
            // c     wn1 is a double precision array of dimension 2m x 2m.
            // c       On entry wn1 stores the lower triangular part of
            // c                     [Y' ZZ'Y   L_a'+R_z']
            // c                     [L_a+R_z   S'AA'S   ]
            // c         in the previous iteration.
            // c       On exit wn1 stores the corresponding updated matrices.
            // c       The purpose of wn1 is just to store these inner products
            // c       so they can be easily updated and inserted into wn.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric corrections
            // c         used to define the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     ws, wy, sy, and wtyy are double precision arrays;
            // c     theta is a double precision variable;
            // c     col is an integer variable;
            // c     head is an integer variable.
            // c       On entry they store the information defining the
            // c                                          limited memory BFGS matrix:
            // c         ws(n,m) stores S, a set of s-vectors;
            // c         wy(n,m) stores Y, a set of y-vectors;
            // c         sy(m,m) stores S'Y;
            // c         wtyy(m,m) stores the Cholesky factorization
            // c                                   of (theta*S'S+LD^(-1)L')
            // c         theta is the scaling factor specifying B_0 = theta I;
            // c         col is the number of variable metric corrections stored;
            // c         head is the location of the 1st s- (or y-) vector in S (or Y).
            // c       On exit they are unchanged.
            // c
            // c     info is an integer variable.
            // c       On entry info is unspecified.
            // c       On exit info =  0 for normal return;
            // c                    = -1 when the 1st Cholesky factorization failed;
            // c                    = -2 when the 2st Cholesky factorization failed.
            // c
            // c     Subprograms called:
            // c
            // c       Linpack ... dcopy, dpofa, dtrsl.
            // c
            // c
            // c     References:
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
            // c       limited memory FORTRAN code for solving bound constrained
            // c       optimization problems'', Tech. Report, NAM-11, EECS Department,
            // c       Northwestern University, 1994.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            // c     Form the lower triangular part of
            // c               WN1 = [Y' ZZ'Y   L_a'+R_z']
            // c                     [L_a+R_z   S'AA'S   ]
            // c        where L_a is the strictly lower triangular part of S'AA'Y
            // c              R_z is the upper triangular part of S'ZZ'Y.


            #endregion


            #region Body

            if (UPDATD)
            {
                if (IUPDAT > M)
                {
                    // c                                 shift old part of WN1.
                    for (JY = 1; JY <= M - 1; JY++)
                    {
                        JS = M + JY;
                        this._dcopy.Run(M - JY, WN1, JY + 1 + (JY + 1) * (2 * M) + o_wn1, 1, ref WN1, JY + JY * (2 * M) + o_wn1, 1);
                        this._dcopy.Run(M - JY, WN1, JS + 1 + (JS + 1) * (2 * M) + o_wn1, 1, ref WN1, JS + JS * (2 * M) + o_wn1, 1);
                        this._dcopy.Run(M - 1, WN1, M + 2 + (JY + 1) * (2 * M) + o_wn1, 1, ref WN1, M + 1 + JY * (2 * M) + o_wn1, 1);
                    }
                }

                // c          put new rows in blocks (1,1), (2,1) and (2,2).
                PBEGIN = 1;
                PEND   = NSUB;
                DBEGIN = NSUB + 1;
                DEND   = N;
                IY     = COL;
                IS     = M + COL;
                IPNTR  = HEAD + COL - 1;
                if (IPNTR > M)
                {
                    IPNTR -= M;
                }
                JPNTR = HEAD;
                for (JY = 1; JY <= COL; JY++)
                {
                    JS    = M + JY;
                    TEMP1 = ZERO;
                    TEMP2 = ZERO;
                    TEMP3 = ZERO;
                    // c             compute element jy of row 'col' of Y'ZZ'Y
                    for (K = PBEGIN; K <= PEND; K++)
                    {
                        K1     = IND[K + o_ind];
                        TEMP1 += WY[K1 + IPNTR * N + o_wy] * WY[K1 + JPNTR * N + o_wy];
                    }
                    // c             compute elements jy of row 'col' of L_a and S'AA'S
                    for (K = DBEGIN; K <= DEND; K++)
                    {
                        K1     = IND[K + o_ind];
                        TEMP2 += WS[K1 + IPNTR * N + o_ws] * WS[K1 + JPNTR * N + o_ws];
                        TEMP3 += WS[K1 + IPNTR * N + o_ws] * WY[K1 + JPNTR * N + o_wy];
                    }
                    WN1[IY + JY * (2 * M) + o_wn1] = TEMP1;
                    WN1[IS + JS * (2 * M) + o_wn1] = TEMP2;
                    WN1[IS + JY * (2 * M) + o_wn1] = TEMP3;
                    JPNTR = FortranLib.Mod(JPNTR, M) + 1;
                }

                // c          put new column in block (2,1).
                JY    = COL;
                JPNTR = HEAD + COL - 1;
                if (JPNTR > M)
                {
                    JPNTR -= M;
                }
                IPNTR = HEAD;
                for (I = 1; I <= COL; I++)
                {
                    IS    = M + I;
                    TEMP3 = ZERO;
                    // c             compute element i of column 'col' of R_z
                    for (K = PBEGIN; K <= PEND; K++)
                    {
                        K1     = IND[K + o_ind];
                        TEMP3 += WS[K1 + IPNTR * N + o_ws] * WY[K1 + JPNTR * N + o_wy];
                    }
                    IPNTR = FortranLib.Mod(IPNTR, M) + 1;
                    WN1[IS + JY * (2 * M) + o_wn1] = TEMP3;
                }
                UPCL = COL - 1;
            }
            else
            {
                UPCL = COL;
            }

            // c       modify the old parts in blocks (1,1) and (2,2) due to changes
            // c       in the set of free variables.
            IPNTR = HEAD;
            for (IY = 1; IY <= UPCL; IY++)
            {
                IS    = M + IY;
                JPNTR = HEAD;
                for (JY = 1; JY <= IY; JY++)
                {
                    JS    = M + JY;
                    TEMP1 = ZERO;
                    TEMP2 = ZERO;
                    TEMP3 = ZERO;
                    TEMP4 = ZERO;
                    for (K = 1; K <= NENTER; K++)
                    {
                        K1     = INDX2[K + o_indx2];
                        TEMP1 += WY[K1 + IPNTR * N + o_wy] * WY[K1 + JPNTR * N + o_wy];
                        TEMP2 += WS[K1 + IPNTR * N + o_ws] * WS[K1 + JPNTR * N + o_ws];
                    }
                    for (K = ILEAVE; K <= N; K++)
                    {
                        K1     = INDX2[K + o_indx2];
                        TEMP3 += WY[K1 + IPNTR * N + o_wy] * WY[K1 + JPNTR * N + o_wy];
                        TEMP4 += WS[K1 + IPNTR * N + o_ws] * WS[K1 + JPNTR * N + o_ws];
                    }
                    WN1[IY + JY * (2 * M) + o_wn1] += TEMP1 - TEMP3;
                    WN1[IS + JS * (2 * M) + o_wn1] += -TEMP2 + TEMP4;
                    JPNTR = FortranLib.Mod(JPNTR, M) + 1;
                }
                IPNTR = FortranLib.Mod(IPNTR, M) + 1;
            }

            // c       modify the old parts in block (2,1).
            IPNTR = HEAD;
            for (IS = M + 1; IS <= M + UPCL; IS++)
            {
                JPNTR = HEAD;
                for (JY = 1; JY <= UPCL; JY++)
                {
                    TEMP1 = ZERO;
                    TEMP3 = ZERO;
                    for (K = 1; K <= NENTER; K++)
                    {
                        K1     = INDX2[K + o_indx2];
                        TEMP1 += WS[K1 + IPNTR * N + o_ws] * WY[K1 + JPNTR * N + o_wy];
                    }
                    for (K = ILEAVE; K <= N; K++)
                    {
                        K1     = INDX2[K + o_indx2];
                        TEMP3 += WS[K1 + IPNTR * N + o_ws] * WY[K1 + JPNTR * N + o_wy];
                    }
                    if (IS <= JY + M)
                    {
                        WN1[IS + JY * (2 * M) + o_wn1] += TEMP1 - TEMP3;
                    }
                    else
                    {
                        WN1[IS + JY * (2 * M) + o_wn1] += -TEMP1 + TEMP3;
                    }
                    JPNTR = FortranLib.Mod(JPNTR, M) + 1;
                }
                IPNTR = FortranLib.Mod(IPNTR, M) + 1;
            }

            // c     Form the upper triangle of WN = [D+Y' ZZ'Y/theta   -L_a'+R_z' ]
            // c                                     [-L_a +R_z        S'AA'S*theta]

            M2 = 2 * M;
            for (IY = 1; IY <= COL; IY++)
            {
                IS    = COL + IY;
                IS1   = M + IY;
                WN_IY = IY * (2 * M) + o_wn;
                for (JY = 1; JY <= IY; JY++)
                {
                    JS             = COL + JY;
                    JS1            = M + JY;
                    WN[JY + WN_IY] = WN1[IY + JY * (2 * M) + o_wn1] / THETA;
                    WN[JS + IS * (2 * M) + o_wn] = WN1[IS1 + JS1 * (2 * M) + o_wn1] * THETA;
                }
                WN_IS = IS * (2 * M) + o_wn;
                for (JY = 1; JY <= IY - 1; JY++)
                {
                    WN[JY + WN_IS] = -WN1[IS1 + JY * (2 * M) + o_wn1];
                }
                WN_IS = IS * (2 * M) + o_wn;
                for (JY = IY; JY <= COL; JY++)
                {
                    WN[JY + WN_IS] = WN1[IS1 + JY * (2 * M) + o_wn1];
                }
                WN[IY + IY * (2 * M) + o_wn] += SY[IY + IY * M + o_sy];
            }

            // c     Form the upper triangle of WN= [  LL'            L^-1(-L_a'+R_z')]
            // c                                    [(-L_a +R_z)L'^-1   S'AA'S*theta  ]

            // c        first Cholesky factor (1,1) block of wn to get LL'
            // c                          with L' stored in the upper triangle of wn.
            this._dpofa.Run(ref WN, offset_wn, M2, COL, ref INFO);
            if (INFO != 0)
            {
                INFO = -1;
                return;
            }
            // c        then form L^-1(-L_a'+R_z') in the (1,2) block.
            COL2 = 2 * COL;
            for (JS = COL + 1; JS <= COL2; JS++)
            {
                this._dtrsl.Run(WN, offset_wn, M2, COL, ref WN, 1 + JS * (2 * M) + o_wn, 11, ref INFO);
            }

            // c     Form S'AA'S*theta + (L^-1(-L_a'+R_z'))'L^-1(-L_a'+R_z') in the
            // c        upper triangle of (2,2) block of wn.


            for (IS = COL + 1; IS <= COL2; IS++)
            {
                for (JS = IS; JS <= COL2; JS++)
                {
                    WN[IS + JS * (2 * M) + o_wn] += this._ddot.Run(COL, WN, 1 + IS * (2 * M) + o_wn, 1, WN, 1 + JS * (2 * M) + o_wn, 1);
                }
            }

            // c     Cholesky factorization of (2,2) block of wn.

            this._dpofa.Run(ref WN, COL + 1 + (COL + 1) * (2 * M) + o_wn, M2, COL, ref INFO);
            if (INFO != 0)
            {
                INFO = -2;
                return;
            }

            return;


            #endregion
        }
Example #14
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x is the starting point for the GCP computation.
        /// On exit x is unchanged.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound of x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound of x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is an integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds, and
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="G">
        /// is a double precision array of dimension n.
        /// On entry g is the gradient of f(x).  g must be a nonzero vector.
        /// On exit g is unchanged.
        ///</param>
        /// <param name="IORDER">
        /// is an integer working array of dimension n.
        /// iorder will be used to store the breakpoints in the piecewise
        /// linear path and free variables encountered. On exit,
        /// iorder(1),...,iorder(nleft) are indices of breakpoints
        /// which have not been encountered;
        /// iorder(nleft+1),...,iorder(nbreak) are indices of
        /// encountered breakpoints; and
        /// iorder(nfree),...,iorder(n) are indices of variables which
        /// have no bound constraits along the search direction.
        ///</param>
        /// <param name="IWHERE">
        /// is an integer array of dimension n.
        /// On entry iwhere indicates only the permanently fixed (iwhere=3)
        /// or free (iwhere= -1) components of x.
        /// On exit iwhere records the status of the current x variables.
        /// iwhere(i)=-3  if x(i) is free and has bounds, but is not moved
        /// 0   if x(i) is free and has bounds, and is moved
        /// 1   if x(i) is fixed at l(i), and l(i) .ne. u(i)
        /// 2   if x(i) is fixed at u(i), and u(i) .ne. l(i)
        /// 3   if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
        /// -1  if x(i) is always free, i.e., it has no bounds.
        ///</param>
        /// <param name="T">
        /// is a double precision working array of dimension n.
        /// t will be used to store the break points.
        ///</param>
        /// <param name="D">
        /// is a double precision array of dimension n used to store
        /// the Cauchy direction P(x-tg)-x.
        ///</param>
        /// <param name="XCP">
        /// is a double precision array of dimension n used to return the
        /// GCP on exit.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="THETA">
        /// is a double precision variable.
        /// On entry theta is the scaling factor specifying B_0 = theta I.
        /// On exit theta is unchanged.
        ///</param>
        /// <param name="COL">
        /// is an integer variable.
        /// On entry col is the actual number of variable metric
        /// corrections stored so far.
        /// On exit col is unchanged.
        ///</param>
        /// <param name="HEAD">
        /// is an integer variable.
        /// On entry head is the location of the first s-vector (or y-vector)
        /// in S (or Y).
        /// On exit col is unchanged.
        ///</param>
        /// <param name="P">
        /// is a double precision working array of dimension 2m.
        /// p will be used to store the vector p = W^(T)d.
        ///</param>
        /// <param name="C">
        /// is a double precision working array of dimension 2m.
        /// c will be used to store the vector c = W^(T)(xcp-x).
        ///</param>
        /// <param name="WBP">
        /// is a double precision working array of dimension 2m.
        /// wbp will be used to store the row of W corresponding
        /// to a breakpoint.
        ///</param>
        /// <param name="V">
        /// is a double precision working array of dimension 2m.
        ///</param>
        /// <param name="NINT">
        /// is an integer variable.
        /// On exit nint records the number of quadratic segments explored
        /// in searching for the GCP.
        ///</param>
        /// <param name="SG">
        /// and yg are double precision arrays of dimension m.
        /// On entry sg  and yg store S'g and Y'g correspondingly.
        /// On exit they are unchanged.
        ///</param>
        /// <param name="IPRINT">
        /// is an INTEGER variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="SBGNRM">
        /// is a double precision variable.
        /// On entry sbgnrm is the norm of the projected gradient at x.
        /// On exit sbgnrm is unchanged.
        ///</param>
        /// <param name="INFO">
        /// is an integer variable.
        /// On entry info is 0.
        /// On exit info = 0       for normal return,
        /// = nonzero for abnormal return when the the system
        /// used in routine bmv is singular.
        ///</param>
        public void Run(int N, double[] X, int offset_x, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd, double[] G, int offset_g
                        , ref int[] IORDER, int offset_iorder, ref int[] IWHERE, int offset_iwhere, ref double[] T, int offset_t, ref double[] D, int offset_d, ref double[] XCP, int offset_xcp, int M
                        , double[] WY, int offset_wy, double[] WS, int offset_ws, double[] SY, int offset_sy, double[] WT, int offset_wt, double THETA, int COL
                        , int HEAD, ref double[] P, int offset_p, ref double[] C, int offset_c, ref double[] WBP, int offset_wbp, ref double[] V, int offset_v, ref int NINT
                        , double[] SG, int offset_sg, double[] YG, int offset_yg, int IPRINT, double SBGNRM, ref int INFO, double EPSMCH)
        {
            #region Variables

            bool   XLOWER = false; bool XUPPER = false; bool BNDED = false; int I = 0; int J = 0; int COL2 = 0; int NFREE = 0;
            int    NBREAK = 0; int POINTR = 0; int IBP = 0; int NLEFT = 0; int IBKMIN = 0; int ITER = 0; double F1 = 0; double F2 = 0;
            double DT = 0; double DTM = 0; double TSUM = 0; double DIBP = 0; double ZIBP = 0; double DIBP2 = 0; double BKMIN = 0;
            double TU = 0; double TL = 0; double WMC = 0; double WMP = 0; double WMW = 0; double TJ = 0; double TJ0 = 0;
            double NEGGI = 0; double F2_ORG = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
            int o_g = -1 + offset_g; int o_iorder = -1 + offset_iorder;  int o_iwhere = -1 + offset_iwhere;
            int o_t = -1 + offset_t; int o_d = -1 + offset_d;  int o_xcp = -1 + offset_xcp;  int o_wy = -1 - N + offset_wy;
            int o_ws = -1 - N + offset_ws; int o_sy = -1 - M + offset_sy;  int o_wt = -1 - M + offset_wt;
            int o_p = -1 + offset_p; int o_c = -1 + offset_c;  int o_wbp = -1 + offset_wbp;  int o_v = -1 + offset_v;
            int o_sg = -1 + offset_sg; int o_yg = -1 + offset_yg;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine cauchy
            // c
            // c     For given x, l, u, g (with sbgnrm > 0), and a limited memory
            // c       BFGS matrix B defined in terms of matrices WY, WS, WT, and
            // c       scalars head, col, and theta, this subroutine computes the
            // c       generalized Cauchy point (GCP), defined as the first local
            // c       minimizer of the quadratic
            // c
            // c                  Q(x + s) = g's + 1/2 s'Bs
            // c
            // c       along the projected gradient direction P(x-tg,l,u).
            // c       The routine returns the GCP in xcp.
            // c
            // c     n is an integer variable.
            // c       On entry n is the dimension of the problem.
            // c       On exit n is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x is the starting point for the GCP computation.
            // c       On exit x is unchanged.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound of x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound of x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is an integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds, and
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     g is a double precision array of dimension n.
            // c       On entry g is the gradient of f(x).  g must be a nonzero vector.
            // c       On exit g is unchanged.
            // c
            // c     iorder is an integer working array of dimension n.
            // c       iorder will be used to store the breakpoints in the piecewise
            // c       linear path and free variables encountered. On exit,
            // c         iorder(1),...,iorder(nleft) are indices of breakpoints
            // c                                which have not been encountered;
            // c         iorder(nleft+1),...,iorder(nbreak) are indices of
            // c                                     encountered breakpoints; and
            // c         iorder(nfree),...,iorder(n) are indices of variables which
            // c                 have no bound constraits along the search direction.
            // c
            // c     iwhere is an integer array of dimension n.
            // c       On entry iwhere indicates only the permanently fixed (iwhere=3)
            // c       or free (iwhere= -1) components of x.
            // c       On exit iwhere records the status of the current x variables.
            // c       iwhere(i)=-3  if x(i) is free and has bounds, but is not moved
            // c                 0   if x(i) is free and has bounds, and is moved
            // c                 1   if x(i) is fixed at l(i), and l(i) .ne. u(i)
            // c                 2   if x(i) is fixed at u(i), and u(i) .ne. l(i)
            // c                 3   if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
            // c                 -1  if x(i) is always free, i.e., it has no bounds.
            // c
            // c     t is a double precision working array of dimension n.
            // c       t will be used to store the break points.
            // c
            // c     d is a double precision array of dimension n used to store
            // c       the Cauchy direction P(x-tg)-x.
            // c
            // c     xcp is a double precision array of dimension n used to return the
            // c       GCP on exit.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric corrections
            // c         used to define the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     ws, wy, sy, and wt are double precision arrays.
            // c       On entry they store information that defines the
            // c                             limited memory BFGS matrix:
            // c         ws(n,m) stores S, a set of s-vectors;
            // c         wy(n,m) stores Y, a set of y-vectors;
            // c         sy(m,m) stores S'Y;
            // c         wt(m,m) stores the
            // c                 Cholesky factorization of (theta*S'S+LD^(-1)L').
            // c       On exit these arrays are unchanged.
            // c
            // c     theta is a double precision variable.
            // c       On entry theta is the scaling factor specifying B_0 = theta I.
            // c       On exit theta is unchanged.
            // c
            // c     col is an integer variable.
            // c       On entry col is the actual number of variable metric
            // c         corrections stored so far.
            // c       On exit col is unchanged.
            // c
            // c     head is an integer variable.
            // c       On entry head is the location of the first s-vector (or y-vector)
            // c         in S (or Y).
            // c       On exit col is unchanged.
            // c
            // c     p is a double precision working array of dimension 2m.
            // c       p will be used to store the vector p = W^(T)d.
            // c
            // c     c is a double precision working array of dimension 2m.
            // c       c will be used to store the vector c = W^(T)(xcp-x).
            // c
            // c     wbp is a double precision working array of dimension 2m.
            // c       wbp will be used to store the row of W corresponding
            // c         to a breakpoint.
            // c
            // c     v is a double precision working array of dimension 2m.
            // c
            // c     nint is an integer variable.
            // c       On exit nint records the number of quadratic segments explored
            // c         in searching for the GCP.
            // c
            // c     sg and yg are double precision arrays of dimension m.
            // c       On entry sg  and yg store S'g and Y'g correspondingly.
            // c       On exit they are unchanged.
            // c
            // c     iprint is an INTEGER variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     sbgnrm is a double precision variable.
            // c       On entry sbgnrm is the norm of the projected gradient at x.
            // c       On exit sbgnrm is unchanged.
            // c
            // c     info is an integer variable.
            // c       On entry info is 0.
            // c       On exit info = 0       for normal return,
            // c                    = nonzero for abnormal return when the the system
            // c                              used in routine bmv is singular.
            // c
            // c     Subprograms called:
            // c
            // c       L-BFGS-B Library ... hpsolb, bmv.
            // c
            // c       Linpack ... dscal dcopy, daxpy.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
            // c       Subroutines for Large Scale Bound Constrained Optimization''
            // c       Tech. Report, NAM-11, EECS Department, Northwestern University,
            // c       1994.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            // c     Check the status of the variables, reset iwhere(i) if necessary;
            // c       compute the Cauchy direction d and the breakpoints t; initialize
            // c       the derivative f1 and the vector p = W'd (for theta = 1).


            #endregion


            #region Body

            if (SBGNRM <= ZERO)
            {
                if (IPRINT >= 0)
                {
                    ;             //ERROR-ERRORWRITE(6,*)'Subgnorm = 0.  GCP = X.'
                }
                this._dcopy.Run(N, X, offset_x, 1, ref XCP, offset_xcp, 1);
                return;
            }
            BNDED  = true;
            NFREE  = N + 1;
            NBREAK = 0;
            IBKMIN = 0;
            BKMIN  = ZERO;
            COL2   = 2 * COL;
            F1     = ZERO;
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,3010)
            }
            // c     We set p to zero and build it up as we determine d.

            for (I = 1; I <= COL2; I++)
            {
                P[I + o_p] = ZERO;
            }

            // c     In the following loop we determine for each variable its bound
            // c        status and its breakpoint, and update p accordingly.
            // c        Smallest breakpoint is identified.

            for (I = 1; I <= N; I++)
            {
                NEGGI = -G[I + o_g];
                if (IWHERE[I + o_iwhere] != 3 && IWHERE[I + o_iwhere] != -1)
                {
                    // c             if x(i) is not a constant and has bounds,
                    // c             compute the difference between x(i) and its bounds.
                    if (NBD[I + o_nbd] <= 2)
                    {
                        TL = X[I + o_x] - L[I + o_l];
                    }
                    if (NBD[I + o_nbd] >= 2)
                    {
                        TU = U[I + o_u] - X[I + o_x];
                    }

                    // c           If a variable is close enough to a bound
                    // c             we treat it as at bound.
                    XLOWER = NBD[I + o_nbd] <= 2 && TL <= ZERO;
                    XUPPER = NBD[I + o_nbd] >= 2 && TU <= ZERO;

                    // c              reset iwhere(i).
                    IWHERE[I + o_iwhere] = 0;
                    if (XLOWER)
                    {
                        if (NEGGI <= ZERO)
                        {
                            IWHERE[I + o_iwhere] = 1;
                        }
                    }
                    else
                    {
                        if (XUPPER)
                        {
                            if (NEGGI >= ZERO)
                            {
                                IWHERE[I + o_iwhere] = 2;
                            }
                        }
                        else
                        {
                            if (Math.Abs(NEGGI) <= ZERO)
                            {
                                IWHERE[I + o_iwhere] = -3;
                            }
                        }
                    }
                }
                POINTR = HEAD;
                if (IWHERE[I + o_iwhere] != 0 && IWHERE[I + o_iwhere] != -1)
                {
                    D[I + o_d] = ZERO;
                }
                else
                {
                    D[I + o_d] = NEGGI;
                    F1        += -NEGGI * NEGGI;
                    // c             calculate p := p - W'e_i* (g_i).
                    for (J = 1; J <= COL; J++)
                    {
                        P[J + o_p]       += WY[I + POINTR * N + o_wy] * NEGGI;
                        P[COL + J + o_p] += WS[I + POINTR * N + o_ws] * NEGGI;
                        POINTR            = FortranLib.Mod(POINTR, M) + 1;
                    }
                    if (NBD[I + o_nbd] <= 2 && NBD[I + o_nbd] != 0 && NEGGI < ZERO)
                    {
                        // c                                 x(i) + d(i) is bounded; compute t(i).
                        NBREAK += 1;
                        IORDER[NBREAK + o_iorder] = I;
                        T[NBREAK + o_t]           = TL / (-NEGGI);
                        if (NBREAK == 1 || T[NBREAK + o_t] < BKMIN)
                        {
                            BKMIN  = T[NBREAK + o_t];
                            IBKMIN = NBREAK;
                        }
                    }
                    else
                    {
                        if (NBD[I + o_nbd] >= 2 && NEGGI > ZERO)
                        {
                            // c                                 x(i) + d(i) is bounded; compute t(i).
                            NBREAK += 1;
                            IORDER[NBREAK + o_iorder] = I;
                            T[NBREAK + o_t]           = TU / NEGGI;
                            if (NBREAK == 1 || T[NBREAK + o_t] < BKMIN)
                            {
                                BKMIN  = T[NBREAK + o_t];
                                IBKMIN = NBREAK;
                            }
                        }
                        else
                        {
                            // c                x(i) + d(i) is not bounded.
                            NFREE -= 1;
                            IORDER[NFREE + o_iorder] = I;
                            if (Math.Abs(NEGGI) > ZERO)
                            {
                                BNDED = false;
                            }
                        }
                    }
                }
            }

            // c     The indices of the nonzero components of d are now stored
            // c       in iorder(1),...,iorder(nbreak) and iorder(nfree),...,iorder(n).
            // c       The smallest of the nbreak breakpoints is in t(ibkmin)=bkmin.

            if (THETA != ONE)
            {
                // c                   complete the initialization of p for theta not= one.
                this._dscal.Run(COL, THETA, ref P, COL + 1 + o_p, 1);
            }

            // c     Initialize GCP xcp = x.

            this._dcopy.Run(N, X, offset_x, 1, ref XCP, offset_xcp, 1);

            if (NBREAK == 0 && NFREE == N + 1)
            {
                // c                  is a zero vector, return with the initial xcp as GCP.
                if (IPRINT > 100)
                {
                    ;              //ERROR-ERRORWRITE(6,1010)(XCP(I),I=1,N)
                }
                return;
            }

            // c     Initialize c = W'(xcp - x) = 0.

            for (J = 1; J <= COL2; J++)
            {
                C[J + o_c] = ZERO;
            }

            // c     Initialize derivative f2.

            F2     = -THETA * F1;
            F2_ORG = F2;
            if (COL > 0)
            {
                this._bmv.Run(M, SY, offset_sy, WT, offset_wt, COL, P, offset_p, ref V, offset_v
                              , ref INFO);
                if (INFO != 0)
                {
                    return;
                }
                F2 -= this._ddot.Run(COL2, V, offset_v, 1, P, offset_p, 1);
            }
            DTM  = -F1 / F2;
            TSUM = ZERO;
            NINT = 1;
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,*)'There are ',NBREAK,'  breakpoints '
            }
            // c     If there are no breakpoints, locate the GCP and return.

            if (NBREAK == 0)
            {
                goto LABEL888;
            }

            NLEFT = NBREAK;
            ITER  = 1;


            TJ = ZERO;

            // c------------------- the beginning of the loop -------------------------

            LABEL777 :;

            // c     Find the next smallest breakpoint;
            // c       compute dt = t(nleft) - t(nleft + 1).

            TJ0 = TJ;
            if (ITER == 1)
            {
                // c         Since we already have the smallest breakpoint we need not do
                // c         heapsort yet. Often only one breakpoint is used and the
                // c         cost of heapsort is avoided.
                TJ  = BKMIN;
                IBP = IORDER[IBKMIN + o_iorder];
            }
            else
            {
                if (ITER == 2)
                {
                    // c             Replace the already used smallest breakpoint with the
                    // c             breakpoint numbered nbreak > nlast, before heapsort call.
                    if (IBKMIN != NBREAK)
                    {
                        T[IBKMIN + o_t]           = T[NBREAK + o_t];
                        IORDER[IBKMIN + o_iorder] = IORDER[NBREAK + o_iorder];
                    }
                    // c        Update heap structure of breakpoints
                    // c           (if iter=2, initialize heap).
                }
                this._hpsolb.Run(NLEFT, ref T, offset_t, ref IORDER, offset_iorder, ITER - 2);
                TJ  = T[NLEFT + o_t];
                IBP = IORDER[NLEFT + o_iorder];
            }

            DT = TJ - TJ0;

            if (DT != ZERO && IPRINT >= 100)
            {
                //ERROR-ERROR         WRITE (6,4011) NINT,F1,F2;
                //ERROR-ERROR         WRITE (6,5010) DT;
                //ERROR-ERROR         WRITE (6,6010) DTM;
            }

            // c     If a minimizer is within this interval, locate the GCP and return.

            if (DTM < DT)
            {
                goto LABEL888;
            }

            // c     Otherwise fix one variable and
            // c       reset the corresponding component of d to zero.

            TSUM        += DT;
            NLEFT       -= 1;
            ITER        += 1;
            DIBP         = D[IBP + o_d];
            D[IBP + o_d] = ZERO;
            if (DIBP > ZERO)
            {
                ZIBP                   = U[IBP + o_u] - X[IBP + o_x];
                XCP[IBP + o_xcp]       = U[IBP + o_u];
                IWHERE[IBP + o_iwhere] = 2;
            }
            else
            {
                ZIBP                   = L[IBP + o_l] - X[IBP + o_x];
                XCP[IBP + o_xcp]       = L[IBP + o_l];
                IWHERE[IBP + o_iwhere] = 1;
            }
            if (IPRINT >= 100)
            {
                ;               //ERROR-ERRORWRITE(6,*)'Variable  ',IBP,'  is fixed.'
            }
            if (NLEFT == 0 && NBREAK == N)
            {
                // c                                             all n variables are fixed,
                // c                                                return with xcp as GCP.
                DTM = DT;
                goto LABEL999;
            }

            // c     Update the derivative information.

            NINT += 1;
            DIBP2 = Math.Pow(DIBP, 2);

            // c     Update f1 and f2.

            // c        temporarily set f1 and f2 for col=0.
            F1 += DT * F2 + DIBP2 - THETA * DIBP * ZIBP;
            F2 += -THETA * DIBP2;

            if (COL > 0)
            {
                // c                          update c = c + dt*p.
                this._daxpy.Run(COL2, DT, P, offset_p, 1, ref C, offset_c, 1);

                // c           choose wbp,
                // c           the row of W corresponding to the breakpoint encountered.
                POINTR = HEAD;
                for (J = 1; J <= COL; J++)
                {
                    WBP[J + o_wbp]       = WY[IBP + POINTR * N + o_wy];
                    WBP[COL + J + o_wbp] = THETA * WS[IBP + POINTR * N + o_ws];
                    POINTR = FortranLib.Mod(POINTR, M) + 1;
                }

                // c           compute (wbp)Mc, (wbp)Mp, and (wbp)M(wbp)'.
                this._bmv.Run(M, SY, offset_sy, WT, offset_wt, COL, WBP, offset_wbp, ref V, offset_v
                              , ref INFO);
                if (INFO != 0)
                {
                    return;
                }
                WMC = this._ddot.Run(COL2, C, offset_c, 1, V, offset_v, 1);
                WMP = this._ddot.Run(COL2, P, offset_p, 1, V, offset_v, 1);
                WMW = this._ddot.Run(COL2, WBP, offset_wbp, 1, V, offset_v, 1);

                // c           update p = p - dibp*wbp.
                this._daxpy.Run(COL2, -DIBP, WBP, offset_wbp, 1, ref P, offset_p, 1);

                // c           complete updating f1 and f2 while col > 0.
                F1 += DIBP * WMC;
                F2 += 2.0E0 * DIBP * WMP - DIBP2 * WMW;
            }

            F2 = Math.Max(EPSMCH * F2_ORG, F2);
            if (NLEFT > 0)
            {
                DTM = -F1 / F2;
                goto LABEL777;
                // c                 to repeat the loop for unsearched intervals.
            }
            else
            {
                if (BNDED)
                {
                    F1  = ZERO;
                    F2  = ZERO;
                    DTM = ZERO;
                }
                else
                {
                    DTM = -F1 / F2;
                }
            }

            // c------------------- the end of the loop -------------------------------

            LABEL888 :;
            if (IPRINT >= 99)
            {
                //ERROR-ERROR         WRITE (6,*);
                //ERROR-ERROR         WRITE (6,*) 'GCP found in this segment';
                //ERROR-ERROR         WRITE (6,4010) NINT,F1,F2;
                //ERROR-ERROR         WRITE (6,6010) DTM;
            }
            if (DTM <= ZERO)
            {
                DTM = ZERO;
            }
            TSUM += DTM;

            // c     Move free variables (i.e., the ones w/o breakpoints) and
            // c       the variables whose breakpoints haven't been reached.

            this._daxpy.Run(N, TSUM, D, offset_d, 1, ref XCP, offset_xcp, 1);

            LABEL999 :;

            // c     Update c = c + dtm*p = W'(x^c - x)
            // c       which will be used in computing r = Z'(B(x^c - x) + g).

            if (COL > 0)
            {
                this._daxpy.Run(COL2, DTM, P, offset_p, 1, ref C, offset_c, 1);
            }
            if (IPRINT > 100)
            {
                ;              //ERROR-ERRORWRITE(6,1010)(XCP(I),I=1,N)
            }
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,2010)
            }
            return;


            #endregion
        }
Example #15
0
        public void Run(int N, double[] X, int offset_x, double F, double[] G, int offset_g, int IPRINT, int ITFILE
                        , int ITER, int NFGV, int NACT, double SBGNRM, int NINT, ref BFGSWord WORD
                        , int IWORD, int IBACK, double STP, double XSTEP)
        {
            #region Variables

            int I = 0; int IMOD = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;  int o_g = -1 + offset_g;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine prn2lb
            // c
            // c     This subroutine prints out new information after a successful
            // c       line search.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************


            // c           'word' records the status of subspace solutions.

            #endregion


            #region Body

            if (IWORD == 0)
            {
                // c                            the subspace minimization converged.
                WORD = BFGSWord.con;
            }
            else
            {
                if (IWORD == 1)
                {
                    // c                          the subspace minimization stopped at a bound.
                    WORD = BFGSWord.bnd;
                }
                else
                {
                    if (IWORD == 5)
                    {
                        // c                             the truncated Newton step has been used.
                        WORD = BFGSWord.tnt;
                    }
                    else
                    {
                        WORD = BFGSWord.aaa;
                    }
                }
            }
            if (IPRINT >= 99)
            {
                //ERROR-ERROR         WRITE (6,*) 'LINE SEARCH',IBACK,' times; norm of step = ',XSTEP;
                //ERROR-ERROR         WRITE (6,2001) ITER,F,SBGNRM;
                if (IPRINT > 100)
                {
                    //ERROR-ERROR            WRITE (6,1004) 'X =',(X(I), I = 1, N);
                    //ERROR-ERROR            WRITE (6,1004) 'G =',(G(I), I = 1, N);
                }
            }
            else
            {
                if (IPRINT > 0)
                {
                    IMOD = FortranLib.Mod(ITER, IPRINT);
                    if (IMOD == 0)
                    {
                        ;           //ERROR-ERRORWRITE(6,2001)ITER,F,SBGNRM
                    }
                }
            }
            if (IPRINT >= 1)
            {
                ;             //ERROR-ERRORWRITE(ITFILE,3001)ITER,NFGV,NINT,NACT,WORD,IBACK,STP,XSTEP,SBGNRM,F
            }
            return;


            #endregion
        }
Example #16
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// interchanges two vectors.
        /// uses unrolled loops for increments equal one.
        /// jack dongarra, linpack, 3/11/78.
        /// modified 12/3/93, array(1) declarations changed to array(*)
        ///</summary>
        public void Run(int N, ref double[] DX, int offset_dx, int INCX, ref double[] DY, int offset_dy, int INCY)
        {
            #region Variables

            double DTEMP = 0; int I = 0; int IX = 0; int IY = 0; int M = 0; int MP1 = 0;

            #endregion


            #region Array Index Correction

            int o_dx = -1 + offset_dx;  int o_dy = -1 + offset_dy;

            #endregion


            #region Prolog

            // *     .. Scalar Arguments ..
            // *     ..
            // *     .. Array Arguments ..
            // *     ..
            // *
            // *  Purpose
            // *  =======
            // *
            // *     interchanges two vectors.
            // *     uses unrolled loops for increments equal one.
            // *     jack dongarra, linpack, 3/11/78.
            // *     modified 12/3/93, array(1) declarations changed to array(*)
            // *
            // *
            // *     .. Local Scalars ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC MOD;
            // *     ..

            #endregion


            #region Body

            if (N <= 0)
            {
                return;
            }
            if (INCX == 1 && INCY == 1)
            {
                goto LABEL20;
            }
            // *
            // *       code for unequal increments or equal increments not equal
            // *         to 1
            // *
            IX = 1;
            IY = 1;
            if (INCX < 0)
            {
                IX = (-N + 1) * INCX + 1;
            }
            if (INCY < 0)
            {
                IY = (-N + 1) * INCY + 1;
            }
            for (I = 1; I <= N; I++)
            {
                DTEMP         = DX[IX + o_dx];
                DX[IX + o_dx] = DY[IY + o_dy];
                DY[IY + o_dy] = DTEMP;
                IX           += INCX;
                IY           += INCY;
            }
            return;

            // *
            // *       code for both increments equal to 1
            // *
            // *
            // *       clean-up loop
            // *
            LABEL20 :  M = FortranLib.Mod(N, 3);
            if (M == 0)
            {
                goto LABEL40;
            }
            for (I = 1; I <= M; I++)
            {
                DTEMP        = DX[I + o_dx];
                DX[I + o_dx] = DY[I + o_dy];
                DY[I + o_dy] = DTEMP;
            }
            if (N < 3)
            {
                return;
            }
            LABEL40 :  MP1 = M + 1;
            for (I = MP1; I <= N; I += 3)
            {
                DTEMP            = DX[I + o_dx];
                DX[I + o_dx]     = DY[I + o_dy];
                DY[I + o_dy]     = DTEMP;
                DTEMP            = DX[I + 1 + o_dx];
                DX[I + 1 + o_dx] = DY[I + 1 + o_dy];
                DY[I + 1 + o_dy] = DTEMP;
                DTEMP            = DX[I + 2 + o_dx];
                DX[I + 2 + o_dx] = DY[I + 2 + o_dy];
                DY[I + 2 + o_dy] = DTEMP;
            }
            return;

            #endregion
        }
Example #17
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// DSTEDC computes all eigenvalues and, optionally, eigenvectors of a
        /// symmetric tridiagonal matrix using the divide and conquer method.
        /// The eigenvectors of a full or band real symmetric matrix can also be
        /// found if DSYTRD or DSPTRD or DSBTRD has been used to reduce this
        /// matrix to tridiagonal form.
        ///
        /// This code 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.  See DLAED3 for details.
        ///
        ///</summary>
        /// <param name="COMPZ">
        /// (input) CHARACTER*1
        /// = 'N':  Compute eigenvalues only.
        /// = 'I':  Compute eigenvectors of tridiagonal matrix also.
        /// = 'V':  Compute eigenvectors of original dense symmetric
        /// matrix also.  On entry, Z contains the orthogonal
        /// matrix used to reduce the original matrix to
        /// tridiagonal form.
        ///</param>
        /// <param name="N">
        /// (input) INTEGER
        /// The dimension of the symmetric tridiagonal matrix.  N .GE. 0.
        ///</param>
        /// <param name="D">
        /// (input/output) DOUBLE PRECISION array, dimension (N)
        /// On entry, the diagonal elements of the tridiagonal matrix.
        /// On exit, if INFO = 0, the eigenvalues in ascending order.
        ///</param>
        /// <param name="E">
        /// (input/output) DOUBLE PRECISION array, dimension (N-1)
        /// On entry, the subdiagonal elements of the tridiagonal matrix.
        /// On exit, E has been destroyed.
        ///</param>
        /// <param name="Z">
        /// (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
        /// On entry, if COMPZ = 'V', then Z contains the orthogonal
        /// matrix used in the reduction to tridiagonal form.
        /// On exit, if INFO = 0, then if COMPZ = 'V', Z contains the
        /// orthonormal eigenvectors of the original symmetric matrix,
        /// and if COMPZ = 'I', Z contains the orthonormal eigenvectors
        /// of the symmetric tridiagonal matrix.
        /// If  COMPZ = 'N', then Z is not referenced.
        ///</param>
        /// <param name="LDZ">
        /// (input) INTEGER
        /// The leading dimension of the array Z.  LDZ .GE. 1.
        /// If eigenvectors are desired, then LDZ .GE. max(1,N).
        ///</param>
        /// <param name="WORK">
        /// (workspace/output) DOUBLE PRECISION array,
        /// dimension (LWORK)
        /// On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
        ///</param>
        /// <param name="LWORK">
        /// (input) INTEGER
        /// The dimension of the array WORK.
        /// If COMPZ = 'N' or N .LE. 1 then LWORK must be at least 1.
        /// If COMPZ = 'V' and N .GT. 1 then LWORK must be at least
        /// ( 1 + 3*N + 2*N*lg N + 3*N**2 ),
        /// where lg( N ) = smallest integer k such
        /// that 2**k .GE. N.
        /// If COMPZ = 'I' and N .GT. 1 then LWORK must be at least
        /// ( 1 + 4*N + N**2 ).
        /// Note that for COMPZ = 'I' or 'V', then if N is less than or
        /// equal to the minimum divide size, usually 25, then LWORK need
        /// only be max(1,2*(N-1)).
        ///
        /// If LWORK = -1, then a workspace query is assumed; the routine
        /// only calculates the optimal size of the WORK array, returns
        /// this value as the first entry of the WORK array, and no error
        /// message related to LWORK is issued by XERBLA.
        ///</param>
        /// <param name="IWORK">
        /// (workspace/output) INTEGER array, dimension (MAX(1,LIWORK))
        /// On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
        ///</param>
        /// <param name="LIWORK">
        /// (input) INTEGER
        /// The dimension of the array IWORK.
        /// If COMPZ = 'N' or N .LE. 1 then LIWORK must be at least 1.
        /// If COMPZ = 'V' and N .GT. 1 then LIWORK must be at least
        /// ( 6 + 6*N + 5*N*lg N ).
        /// If COMPZ = 'I' and N .GT. 1 then LIWORK must be at least
        /// ( 3 + 5*N ).
        /// Note that for COMPZ = 'I' or 'V', then if N is less than or
        /// equal to the minimum divide size, usually 25, then LIWORK
        /// need only be 1.
        ///
        /// If LIWORK = -1, then a workspace query is assumed; the
        /// routine only calculates the optimal size of the IWORK array,
        /// returns this value as the first entry of the IWORK array, and
        /// no error message related to LIWORK is issued by XERBLA.
        ///</param>
        /// <param name="INFO">
        /// (output) INTEGER
        /// = 0:  successful exit.
        /// .LT. 0:  if INFO = -i, the i-th argument had an illegal value.
        /// .GT. 0:  The algorithm failed to compute an eigenvalue while
        /// working on the submatrix lying in rows and columns
        /// INFO/(N+1) through mod(INFO,N+1).
        ///</param>
        public void Run(string COMPZ, int N, ref double[] D, int offset_d, ref double[] E, int offset_e, ref double[] Z, int offset_z, int LDZ
                        , ref double[] WORK, int offset_work, int LWORK, ref int[] IWORK, int offset_iwork, int LIWORK, ref int INFO)
        {
            #region Variables

            bool   LQUERY = false; int FINISH = 0; int I = 0; int ICOMPZ = 0; int II = 0; int J = 0; int K = 0; int LGN = 0;
            int    LIWMIN = 0; int LWMIN = 0; int M = 0; int SMLSIZ = 0; int START = 0; int STOREZ = 0; int STRTRW = 0;
            double EPS = 0; double ORGNRM = 0; double P = 0; double TINY = 0;

            #endregion


            #region Array Index Correction

            int o_d = -1 + offset_d;  int o_e = -1 + offset_e;  int o_z = -1 - LDZ + offset_z;  int o_work = -1 + offset_work;
            int o_iwork = -1 + offset_iwork;

            #endregion


            #region Strings

            COMPZ = COMPZ.Substring(0, 1);

            #endregion


            #region Prolog

            // *
            // *  -- LAPACK driver routine (version 3.1) --
            // *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
            // *     November 2006
            // *
            // *     .. Scalar Arguments ..
            // *     ..
            // *     .. Array Arguments ..
            // *     ..
            // *
            // *  Purpose
            // *  =======
            // *
            // *  DSTEDC computes all eigenvalues and, optionally, eigenvectors of a
            // *  symmetric tridiagonal matrix using the divide and conquer method.
            // *  The eigenvectors of a full or band real symmetric matrix can also be
            // *  found if DSYTRD or DSPTRD or DSBTRD has been used to reduce this
            // *  matrix to tridiagonal form.
            // *
            // *  This code 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.  See DLAED3 for details.
            // *
            // *  Arguments
            // *  =========
            // *
            // *  COMPZ   (input) CHARACTER*1
            // *          = 'N':  Compute eigenvalues only.
            // *          = 'I':  Compute eigenvectors of tridiagonal matrix also.
            // *          = 'V':  Compute eigenvectors of original dense symmetric
            // *                  matrix also.  On entry, Z contains the orthogonal
            // *                  matrix used to reduce the original matrix to
            // *                  tridiagonal form.
            // *
            // *  N       (input) INTEGER
            // *          The dimension of the symmetric tridiagonal matrix.  N >= 0.
            // *
            // *  D       (input/output) DOUBLE PRECISION array, dimension (N)
            // *          On entry, the diagonal elements of the tridiagonal matrix.
            // *          On exit, if INFO = 0, the eigenvalues in ascending order.
            // *
            // *  E       (input/output) DOUBLE PRECISION array, dimension (N-1)
            // *          On entry, the subdiagonal elements of the tridiagonal matrix.
            // *          On exit, E has been destroyed.
            // *
            // *  Z       (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
            // *          On entry, if COMPZ = 'V', then Z contains the orthogonal
            // *          matrix used in the reduction to tridiagonal form.
            // *          On exit, if INFO = 0, then if COMPZ = 'V', Z contains the
            // *          orthonormal eigenvectors of the original symmetric matrix,
            // *          and if COMPZ = 'I', Z contains the orthonormal eigenvectors
            // *          of the symmetric tridiagonal matrix.
            // *          If  COMPZ = 'N', then Z is not referenced.
            // *
            // *  LDZ     (input) INTEGER
            // *          The leading dimension of the array Z.  LDZ >= 1.
            // *          If eigenvectors are desired, then LDZ >= max(1,N).
            // *
            // *  WORK    (workspace/output) DOUBLE PRECISION array,
            // *                                         dimension (LWORK)
            // *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
            // *
            // *  LWORK   (input) INTEGER
            // *          The dimension of the array WORK.
            // *          If COMPZ = 'N' or N <= 1 then LWORK must be at least 1.
            // *          If COMPZ = 'V' and N > 1 then LWORK must be at least
            // *                         ( 1 + 3*N + 2*N*lg N + 3*N**2 ),
            // *                         where lg( N ) = smallest integer k such
            // *                         that 2**k >= N.
            // *          If COMPZ = 'I' and N > 1 then LWORK must be at least
            // *                         ( 1 + 4*N + N**2 ).
            // *          Note that for COMPZ = 'I' or 'V', then if N is less than or
            // *          equal to the minimum divide size, usually 25, then LWORK need
            // *          only be max(1,2*(N-1)).
            // *
            // *          If LWORK = -1, then a workspace query is assumed; the routine
            // *          only calculates the optimal size of the WORK array, returns
            // *          this value as the first entry of the WORK array, and no error
            // *          message related to LWORK is issued by XERBLA.
            // *
            // *  IWORK   (workspace/output) INTEGER array, dimension (MAX(1,LIWORK))
            // *          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
            // *
            // *  LIWORK  (input) INTEGER
            // *          The dimension of the array IWORK.
            // *          If COMPZ = 'N' or N <= 1 then LIWORK must be at least 1.
            // *          If COMPZ = 'V' and N > 1 then LIWORK must be at least
            // *                         ( 6 + 6*N + 5*N*lg N ).
            // *          If COMPZ = 'I' and N > 1 then LIWORK must be at least
            // *                         ( 3 + 5*N ).
            // *          Note that for COMPZ = 'I' or 'V', then if N is less than or
            // *          equal to the minimum divide size, usually 25, then LIWORK
            // *          need only be 1.
            // *
            // *          If LIWORK = -1, then a workspace query is assumed; the
            // *          routine only calculates the optimal size of the IWORK array,
            // *          returns this value as the first entry of the IWORK array, and
            // *          no error message related to LIWORK is issued by XERBLA.
            // *
            // *  INFO    (output) INTEGER
            // *          = 0:  successful exit.
            // *          < 0:  if INFO = -i, the i-th argument had an illegal value.
            // *          > 0:  The algorithm failed to compute an eigenvalue while
            // *                working on the submatrix lying in rows and columns
            // *                INFO/(N+1) through mod(INFO,N+1).
            // *
            // *  Further Details
            // *  ===============
            // *
            // *  Based on contributions by
            // *     Jeff Rutter, Computer Science Division, University of California
            // *     at Berkeley, USA
            // *  Modified by Francoise Tisseur, University of Tennessee.
            // *
            // *  =====================================================================
            // *
            // *     .. Parameters ..
            // *     ..
            // *     .. Local Scalars ..
            // *     ..
            // *     .. External Functions ..
            // *     ..
            // *     .. External Subroutines ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC          ABS, DBLE, INT, LOG, MAX, MOD, SQRT;
            // *     ..
            // *     .. Executable Statements ..
            // *
            // *     Test the input parameters.
            // *

            #endregion


            #region Body

            INFO   = 0;
            LQUERY = (LWORK == -1 || LIWORK == -1);
            // *
            if (this._lsame.Run(COMPZ, "N"))
            {
                ICOMPZ = 0;
            }
            else
            {
                if (this._lsame.Run(COMPZ, "V"))
                {
                    ICOMPZ = 1;
                }
                else
                {
                    if (this._lsame.Run(COMPZ, "I"))
                    {
                        ICOMPZ = 2;
                    }
                    else
                    {
                        ICOMPZ = -1;
                    }
                }
            }
            if (ICOMPZ < 0)
            {
                INFO = -1;
            }
            else
            {
                if (N < 0)
                {
                    INFO = -2;
                }
                else
                {
                    if ((LDZ < 1) || (ICOMPZ > 0 && LDZ < Math.Max(1, N)))
                    {
                        INFO = -6;
                    }
                }
            }
            // *
            if (INFO == 0)
            {
                // *
                // *        Compute the workspace requirements
                // *
                SMLSIZ = this._ilaenv.Run(9, "DSTEDC", " ", 0, 0, 0, 0);
                if (N <= 1 || ICOMPZ == 0)
                {
                    LIWMIN = 1;
                    LWMIN  = 1;
                }
                else
                {
                    if (N <= SMLSIZ)
                    {
                        LIWMIN = 1;
                        LWMIN  = 2 * (N - 1);
                    }
                    else
                    {
                        LGN = Convert.ToInt32(Math.Truncate(Math.Log(Convert.ToDouble(N)) / Math.Log(TWO)));
                        if (Math.Pow(2, LGN) < N)
                        {
                            LGN += 1;
                        }
                        if (Math.Pow(2, LGN) < N)
                        {
                            LGN += 1;
                        }
                        if (ICOMPZ == 1)
                        {
                            LWMIN  = 1 + 3 * N + 2 * N * LGN + 3 * (int)Math.Pow(N, 2);
                            LIWMIN = 6 + 6 * N + 5 * N * LGN;
                        }
                        else
                        {
                            if (ICOMPZ == 2)
                            {
                                LWMIN  = 1 + 4 * N + (int)Math.Pow(N, 2);
                                LIWMIN = 3 + 5 * N;
                            }
                        }
                    }
                }
                WORK[1 + o_work]   = LWMIN;
                IWORK[1 + o_iwork] = LIWMIN;
                // *
                if (LWORK < LWMIN && !LQUERY)
                {
                    INFO = -8;
                }
                else
                {
                    if (LIWORK < LIWMIN && !LQUERY)
                    {
                        INFO = -10;
                    }
                }
            }
            // *
            if (INFO != 0)
            {
                this._xerbla.Run("DSTEDC", -INFO);
                return;
            }
            else
            {
                if (LQUERY)
                {
                    return;
                }
            }
            // *
            // *     Quick return if possible
            // *
            if (N == 0)
            {
                return;
            }
            if (N == 1)
            {
                if (ICOMPZ != 0)
                {
                    Z[1 + 1 * LDZ + o_z] = ONE;
                }
                return;
            }
            // *
            // *     If the following conditional clause is removed, then the routine
            // *     will use the Divide and Conquer routine to compute only the
            // *     eigenvalues, which requires (3N + 3N**2) real workspace and
            // *     (2 + 5N + 2N lg(N)) integer workspace.
            // *     Since on many architectures DSTERF is much faster than any other
            // *     algorithm for finding eigenvalues only, it is used here
            // *     as the default. If the conditional clause is removed, then
            // *     information on the size of workspace needs to be changed.
            // *
            // *     If COMPZ = 'N', use DSTERF to compute the eigenvalues.
            // *
            if (ICOMPZ == 0)
            {
                this._dsterf.Run(N, ref D, offset_d, ref E, offset_e, ref INFO);
                goto LABEL50;
            }
            // *
            // *     If N is smaller than the minimum divide size (SMLSIZ+1), then
            // *     solve the problem with another solver.
            // *
            if (N <= SMLSIZ)
            {
                // *
                this._dsteqr.Run(COMPZ, N, ref D, offset_d, ref E, offset_e, ref Z, offset_z, LDZ
                                 , ref WORK, offset_work, ref INFO);
                // *
            }
            else
            {
                // *
                // *        If COMPZ = 'V', the Z matrix must be stored elsewhere for later
                // *        use.
                // *
                if (ICOMPZ == 1)
                {
                    STOREZ = 1 + N * N;
                }
                else
                {
                    STOREZ = 1;
                }
                // *
                if (ICOMPZ == 2)
                {
                    this._dlaset.Run("Full", N, N, ZERO, ONE, ref Z, offset_z
                                     , LDZ);
                }
                // *
                // *        Scale.
                // *
                ORGNRM = this._dlanst.Run("M", N, D, offset_d, E, offset_e);
                if (ORGNRM == ZERO)
                {
                    goto LABEL50;
                }
                // *
                EPS = this._dlamch.Run("Epsilon");
                // *
                START = 1;
                // *
                // *        while ( START <= N )
                // *
                LABEL10 :;
                if (START <= N)
                {
                    // *
                    // *           Let FINISH be the position of the next subdiagonal entry
                    // *           such that E( FINISH ) <= TINY or FINISH = N if no such
                    // *           subdiagonal exists.  The matrix identified by the elements
                    // *           between START and FINISH constitutes an independent
                    // *           sub-problem.
                    // *
                    FINISH = START;
                    LABEL20 :;
                    if (FINISH < N)
                    {
                        TINY = EPS * Math.Sqrt(Math.Abs(D[FINISH + o_d])) * Math.Sqrt(Math.Abs(D[FINISH + 1 + o_d]));
                        if (Math.Abs(E[FINISH + o_e]) > TINY)
                        {
                            FINISH += 1;
                            goto LABEL20;
                        }
                    }
                    // *
                    // *           (Sub) Problem determined.  Compute its size and solve it.
                    // *
                    M = FINISH - START + 1;
                    if (M == 1)
                    {
                        START = FINISH + 1;
                        goto LABEL10;
                    }
                    if (M > SMLSIZ)
                    {
                        // *
                        // *              Scale.
                        // *
                        ORGNRM = this._dlanst.Run("M", M, D, START + o_d, E, START + o_e);
                        this._dlascl.Run("G", 0, 0, ORGNRM, ONE, M
                                         , 1, ref D, START + o_d, M, ref INFO);
                        this._dlascl.Run("G", 0, 0, ORGNRM, ONE, M - 1
                                         , 1, ref E, START + o_e, M - 1, ref INFO);
                        // *
                        if (ICOMPZ == 1)
                        {
                            STRTRW = 1;
                        }
                        else
                        {
                            STRTRW = START;
                        }
                        this._dlaed0.Run(ICOMPZ, N, M, ref D, START + o_d, ref E, START + o_e, ref Z, STRTRW + START * LDZ + o_z
                                         , LDZ, ref WORK, 1 + o_work, N, ref WORK, STOREZ + o_work, ref IWORK, offset_iwork, ref INFO);
                        if (INFO != 0)
                        {
                            INFO = (INFO / (M + 1) + START - 1) * (N + 1) + FortranLib.Mod(INFO, (M + 1)) + START - 1;
                            goto LABEL50;
                        }
                        // *
                        // *              Scale back.
                        // *
                        this._dlascl.Run("G", 0, 0, ONE, ORGNRM, M
                                         , 1, ref D, START + o_d, M, ref INFO);
                        // *
                    }
                    else
                    {
                        if (ICOMPZ == 1)
                        {
                            // *
                            // *                 Since QR won't update a Z matrix which is larger than
                            // *                 the length of D, we must solve the sub-problem in a
                            // *                 workspace and then multiply back into Z.
                            // *
                            this._dsteqr.Run("I", M, ref D, START + o_d, ref E, START + o_e, ref WORK, offset_work, M
                                             , ref WORK, M * M + 1 + o_work, ref INFO);
                            this._dlacpy.Run("A", N, M, Z, 1 + START * LDZ + o_z, LDZ, ref WORK, STOREZ + o_work
                                             , N);
                            this._dgemm.Run("N", "N", N, M, M, ONE
                                            , WORK, STOREZ + o_work, N, WORK, offset_work, M, ZERO, ref Z, 1 + START * LDZ + o_z
                                            , LDZ);
                        }
                        else
                        {
                            if (ICOMPZ == 2)
                            {
                                this._dsteqr.Run("I", M, ref D, START + o_d, ref E, START + o_e, ref Z, START + START * LDZ + o_z, LDZ
                                                 , ref WORK, offset_work, ref INFO);
                            }
                            else
                            {
                                this._dsterf.Run(M, ref D, START + o_d, ref E, START + o_e, ref INFO);
                            }
                        }
                        if (INFO != 0)
                        {
                            INFO = START * (N + 1) + FINISH;
                            goto LABEL50;
                        }
                    }
                    // *
                    START = FINISH + 1;
                    goto LABEL10;
                }
                // *
                // *        endwhile
                // *
                // *        If the problem split any number of times, then the eigenvalues
                // *        will not be properly ordered.  Here we permute the eigenvalues
                // *        (and the associated eigenvectors) into ascending order.
                // *
                if (M != N)
                {
                    if (ICOMPZ == 0)
                    {
                        // *
                        // *              Use Quick Sort
                        // *
                        this._dlasrt.Run("I", N, ref D, offset_d, ref INFO);
                        // *
                    }
                    else
                    {
                        // *
                        // *              Use Selection Sort to minimize swaps of eigenvectors
                        // *
                        for (II = 2; II <= N; II++)
                        {
                            I = II - 1;
                            K = I;
                            P = D[I + o_d];
                            for (J = II; J <= N; J++)
                            {
                                if (D[J + o_d] < P)
                                {
                                    K = J;
                                    P = D[J + o_d];
                                }
                            }
                            if (K != I)
                            {
                                D[K + o_d] = D[I + o_d];
                                D[I + o_d] = P;
                                this._dswap.Run(N, ref Z, 1 + I * LDZ + o_z, 1, ref Z, 1 + K * LDZ + o_z, 1);
                            }
                        }
                    }
                }
            }
            // *
            LABEL50 :;
            WORK[1 + o_work]   = LWMIN;
            IWORK[1 + o_iwork] = LIWMIN;
            // *
            return;

            // *
            // *     End of DSTEDC
            // *

            #endregion
        }
Example #18
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// This program sets problem and machine dependent parameters
        /// useful for xHSEQR and its subroutines. It is called whenever
        /// ILAENV is called with 12 .LE. ISPEC .LE. 16
        ///
        ///</summary>
        /// <param name="ISPEC">
        /// (input) integer scalar
        /// ISPEC specifies which tunable parameter IPARMQ should
        /// return.
        ///
        /// ISPEC=12: (INMIN)  Matrices of order nmin or less
        /// are sent directly to xLAHQR, the implicit
        /// double shift QR algorithm.  NMIN must be
        /// at least 11.
        ///
        /// ISPEC=13: (INWIN)  Size of the deflation window.
        /// This is best set greater than or equal to
        /// the number of simultaneous shifts NS.
        /// Larger matrices benefit from larger deflation
        /// windows.
        ///
        /// ISPEC=14: (INIBL) Determines when to stop nibbling and
        /// invest in an (expensive) multi-shift QR sweep.
        /// If the aggressive early deflation subroutine
        /// finds LD converged eigenvalues from an order
        /// NW deflation window and LD.GT.(NW*NIBBLE)/100,
        /// then the next QR sweep is skipped and early
        /// deflation is applied immediately to the
        /// remaining active diagonal block.  Setting
        /// IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a
        /// multi-shift QR sweep whenever early deflation
        /// finds a converged eigenvalue.  Setting
        /// IPARMQ(ISPEC=14) greater than or equal to 100
        /// prevents TTQRE from skipping a multi-shift
        /// QR sweep.
        ///
        /// ISPEC=15: (NSHFTS) The number of simultaneous shifts in
        /// a multi-shift QR iteration.
        ///
        /// ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the
        /// following meanings.
        /// 0:  During the multi-shift QR sweep,
        /// xLAQR5 does not accumulate reflections and
        /// does not use matrix-matrix multiply to
        /// update the far-from-diagonal matrix
        /// entries.
        /// 1:  During the multi-shift QR sweep,
        /// xLAQR5 and/or xLAQRaccumulates reflections and uses
        /// matrix-matrix multiply to update the
        /// far-from-diagonal matrix entries.
        /// 2:  During the multi-shift QR sweep.
        /// xLAQR5 accumulates reflections and takes
        /// advantage of 2-by-2 block structure during
        /// matrix-matrix multiplies.
        /// (If xTRMM is slower than xGEMM, then
        /// IPARMQ(ISPEC=16)=1 may be more efficient than
        /// IPARMQ(ISPEC=16)=2 despite the greater level of
        /// arithmetic work implied by the latter choice.)
        ///</param>
        /// <param name="NAME">
        /// (input) character string
        /// Name of the calling subroutine
        ///</param>
        /// <param name="OPTS">
        /// (input) character string
        /// This is a concatenation of the string arguments to
        /// TTQRE.
        ///</param>
        /// <param name="N">
        /// (input) integer scalar
        /// N is the order of the Hessenberg matrix H.
        ///</param>
        /// <param name="ILO">
        /// (input) INTEGER
        ///</param>
        /// <param name="IHI">
        /// (input) INTEGER
        /// It is assumed that H is already upper triangular
        /// in rows and columns 1:ILO-1 and IHI+1:N.
        ///</param>
        /// <param name="LWORK">
        /// (input) integer scalar
        /// The amount of workspace available.
        ///</param>
        public int Run(int ISPEC, string NAME, string OPTS, int N, int ILO, int IHI
                       , int LWORK)
        {
            int iparmq = 0;

            #region Variables

            int NH = 0; int NS = 0;

            #endregion


            #region Prolog

            // *
            // *  -- LAPACK auxiliary routine (version 3.1) --
            // *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
            // *     November 2006
            // *
            // *     .. Scalar Arguments ..
            // *
            // *  Purpose
            // *  =======
            // *
            // *       This program sets problem and machine dependent parameters
            // *       useful for xHSEQR and its subroutines. It is called whenever
            // *       ILAENV is called with 12 <= ISPEC <= 16
            // *
            // *  Arguments
            // *  =========
            // *
            // *       ISPEC  (input) integer scalar
            // *              ISPEC specifies which tunable parameter IPARMQ should
            // *              return.
            // *
            // *              ISPEC=12: (INMIN)  Matrices of order nmin or less
            // *                        are sent directly to xLAHQR, the implicit
            // *                        double shift QR algorithm.  NMIN must be
            // *                        at least 11.
            // *
            // *              ISPEC=13: (INWIN)  Size of the deflation window.
            // *                        This is best set greater than or equal to
            // *                        the number of simultaneous shifts NS.
            // *                        Larger matrices benefit from larger deflation
            // *                        windows.
            // *
            // *              ISPEC=14: (INIBL) Determines when to stop nibbling and
            // *                        invest in an (expensive) multi-shift QR sweep.
            // *                        If the aggressive early deflation subroutine
            // *                        finds LD converged eigenvalues from an order
            // *                        NW deflation window and LD.GT.(NW*NIBBLE)/100,
            // *                        then the next QR sweep is skipped and early
            // *                        deflation is applied immediately to the
            // *                        remaining active diagonal block.  Setting
            // *                        IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a
            // *                        multi-shift QR sweep whenever early deflation
            // *                        finds a converged eigenvalue.  Setting
            // *                        IPARMQ(ISPEC=14) greater than or equal to 100
            // *                        prevents TTQRE from skipping a multi-shift
            // *                        QR sweep.
            // *
            // *              ISPEC=15: (NSHFTS) The number of simultaneous shifts in
            // *                        a multi-shift QR iteration.
            // *
            // *              ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the
            // *                        following meanings.
            // *                        0:  During the multi-shift QR sweep,
            // *                            xLAQR5 does not accumulate reflections and
            // *                            does not use matrix-matrix multiply to
            // *                            update the far-from-diagonal matrix
            // *                            entries.
            // *                        1:  During the multi-shift QR sweep,
            // *                            xLAQR5 and/or xLAQRaccumulates reflections and uses
            // *                            matrix-matrix multiply to update the
            // *                            far-from-diagonal matrix entries.
            // *                        2:  During the multi-shift QR sweep.
            // *                            xLAQR5 accumulates reflections and takes
            // *                            advantage of 2-by-2 block structure during
            // *                            matrix-matrix multiplies.
            // *                        (If xTRMM is slower than xGEMM, then
            // *                        IPARMQ(ISPEC=16)=1 may be more efficient than
            // *                        IPARMQ(ISPEC=16)=2 despite the greater level of
            // *                        arithmetic work implied by the latter choice.)
            // *
            // *       NAME    (input) character string
            // *               Name of the calling subroutine
            // *
            // *       OPTS    (input) character string
            // *               This is a concatenation of the string arguments to
            // *               TTQRE.
            // *
            // *       N       (input) integer scalar
            // *               N is the order of the Hessenberg matrix H.
            // *
            // *       ILO     (input) INTEGER
            // *       IHI     (input) INTEGER
            // *               It is assumed that H is already upper triangular
            // *               in rows and columns 1:ILO-1 and IHI+1:N.
            // *
            // *       LWORK   (input) integer scalar
            // *               The amount of workspace available.
            // *
            // *  Further Details
            // *  ===============
            // *
            // *       Little is known about how best to choose these parameters.
            // *       It is possible to use different values of the parameters
            // *       for each of CHSEQR, DHSEQR, SHSEQR and ZHSEQR.
            // *
            // *       It is probably best to choose different parameters for
            // *       different matrices and different parameters at different
            // *       times during the iteration, but this has not been
            // *       implemented --- yet.
            // *
            // *
            // *       The best choices of most of the parameters depend
            // *       in an ill-understood way on the relative execution
            // *       rate of xLAQR3 and xLAQR5 and on the nature of each
            // *       particular eigenvalue problem.  Experiment may be the
            // *       only practical way to determine which choices are most
            // *       effective.
            // *
            // *       Following is a list of default values supplied by IPARMQ.
            // *       These defaults may be adjusted in order to attain better
            // *       performance in any particular computational environment.
            // *
            // *       IPARMQ(ISPEC=12) The xLAHQR vs xLAQR0 crossover point.
            // *                        Default: 75. (Must be at least 11.)
            // *
            // *       IPARMQ(ISPEC=13) Recommended deflation window size.
            // *                        This depends on ILO, IHI and NS, the
            // *                        number of simultaneous shifts returned
            // *                        by IPARMQ(ISPEC=15).  The default for
            // *                        (IHI-ILO+1).LE.500 is NS.  The default
            // *                        for (IHI-ILO+1).GT.500 is 3*NS/2.
            // *
            // *       IPARMQ(ISPEC=14) Nibble crossover point.  Default: 14.
            // *
            // *       IPARMQ(ISPEC=15) Number of simultaneous shifts, NS.
            // *                        a multi-shift QR iteration.
            // *
            // *                        If IHI-ILO+1 is ...
            // *
            // *                        greater than      ...but less    ... the
            // *                        or equal to ...      than        default is
            // *
            // *                                0               30       NS =   2+
            // *                               30               60       NS =   4+
            // *                               60              150       NS =  10
            // *                              150              590       NS =  **
            // *                              590             3000       NS =  64
            // *                             3000             6000       NS = 128
            // *                             6000             infinity   NS = 256
            // *
            // *                    (+)  By default matrices of this order are
            // *                         passed to the implicit double shift routine
            // *                         xLAHQR.  See IPARMQ(ISPEC=12) above.   These
            // *                         values of NS are used only in case of a rare
            // *                         xLAHQR failure.
            // *
            // *                    (**) The asterisks (**) indicate an ad-hoc
            // *                         function increasing from 10 to 64.
            // *
            // *       IPARMQ(ISPEC=16) Select structured matrix multiply.
            // *                        (See ISPEC=16 above for details.)
            // *                        Default: 3.
            // *
            // *     ================================================================
            // *     .. Parameters ..
            // *     ..
            // *     .. Local Scalars ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC          LOG, MAX, MOD, NINT, REAL;
            // *     ..
            // *     .. Executable Statements ..

            #endregion


            #region Body

            if ((ISPEC == ISHFTS) || (ISPEC == INWIN) || (ISPEC == IACC22))
            {
                // *
                // *        ==== Set the number simultaneous shifts ====
                // *
                NH = IHI - ILO + 1;
                NS = 2;
                if (NH >= 30)
                {
                    NS = 4;
                }
                if (NH >= 60)
                {
                    NS = 10;
                }
                if (NH >= 150)
                {
                    NS = (int)Math.Max(10, NH / Math.Round(Math.Log(Convert.ToSingle(NH)) / Math.Log(TWO)));
                }
                if (NH >= 590)
                {
                    NS = 64;
                }
                if (NH >= 3000)
                {
                    NS = 128;
                }
                if (NH >= 6000)
                {
                    NS = 256;
                }
                NS = Math.Max(2, NS - FortranLib.Mod(NS, 2));
            }
            // *
            if (ISPEC == INMIN)
            {
                // *
                // *
                // *        ===== Matrices of order smaller than NMIN get sent
                // *        .     to xLAHQR, the classic double shift algorithm.
                // *        .     This must be at least 11. ====
                // *
                iparmq = NMIN;
                // *
            }
            else
            {
                if (ISPEC == INIBL)
                {
                    // *
                    // *        ==== INIBL: skip a multi-shift qr iteration and
                    // *        .    whenever aggressive early deflation finds
                    // *        .    at least (NIBBLE*(window size)/100) deflations. ====
                    // *
                    iparmq = NIBBLE;
                    // *
                }
                else
                {
                    if (ISPEC == ISHFTS)
                    {
                        // *
                        // *        ==== NSHFTS: The number of simultaneous shifts =====
                        // *
                        iparmq = NS;
                        // *
                    }
                    else
                    {
                        if (ISPEC == INWIN)
                        {
                            // *
                            // *        ==== NW: deflation window size.  ====
                            // *
                            if (NH <= KNWSWP)
                            {
                                iparmq = NS;
                            }
                            else
                            {
                                iparmq = 3 * NS / 2;
                            }
                            // *
                        }
                        else
                        {
                            if (ISPEC == IACC22)
                            {
                                // *
                                // *        ==== IACC22: Whether to accumulate reflections
                                // *        .     before updating the far-from-diagonal elements
                                // *        .     and whether to use 2-by-2 block structure while
                                // *        .     doing it.  A small amount of work could be saved
                                // *        .     by making this choice dependent also upon the
                                // *        .     NH=IHI-ILO+1.
                                // *
                                iparmq = 0;
                                if (NS >= KACMIN)
                                {
                                    iparmq = 1;
                                }
                                if (NS >= K22MIN)
                                {
                                    iparmq = 2;
                                }
                                // *
                            }
                            else
                            {
                                // *        ===== invalid value of ispec =====
                                iparmq = -1;
                                // *
                            }
                        }
                    }
                }
            }
            // *
            // *     ==== End of IPARMQ ====
            // *
            return(iparmq);

            #endregion
        }