Beispiel #1
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// ILAENV is called from the LAPACK routines to choose problem-dependent
        /// parameters for the local environment.  See ISPEC for a description of
        /// the parameters.
        ///
        /// ILAENV returns an INTEGER
        /// if ILAENV .GE. 0: ILAENV returns the value of the parameter specified by ISPEC
        /// if ILAENV .LT. 0:  if ILAENV = -k, the k-th argument had an illegal value.
        ///
        /// This version provides a set of parameters which should give good,
        /// but not optimal, performance on many of the currently available
        /// computers.  Users are encouraged to modify this subroutine to set
        /// the tuning parameters for their particular machine using the option
        /// and problem size information in the arguments.
        ///
        /// This routine will not function correctly if it is converted to all
        /// lower case.  Converting it to all upper case is allowed.
        ///
        ///</summary>
        /// <param name="ISPEC">
        /// (input) INTEGER
        /// Specifies the parameter to be returned as the value of
        /// ILAENV.
        /// = 1: the optimal blocksize; if this value is 1, an unblocked
        /// algorithm will give the best performance.
        /// = 2: the minimum block size for which the block routine
        /// should be used; if the usable block size is less than
        /// this value, an unblocked routine should be used.
        /// = 3: the crossover point (in a block routine, for N less
        /// than this value, an unblocked routine should be used)
        /// = 4: the number of shifts, used in the nonsymmetric
        /// eigenvalue routines (DEPRECATED)
        /// = 5: the minimum column dimension for blocking to be used;
        /// rectangular blocks must have dimension at least k by m,
        /// where k is given by ILAENV(2,...) and m by ILAENV(5,...)
        /// = 6: the crossover point for the SVD (when reducing an m by n
        /// matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds
        /// this value, a QR factorization is used first to reduce
        /// the matrix to a triangular form.)
        /// = 7: the number of processors
        /// = 8: the crossover point for the multishift QR method
        /// for nonsymmetric eigenvalue problems (DEPRECATED)
        /// = 9: maximum size of the subproblems at the bottom of the
        /// computation tree in the divide-and-conquer algorithm
        /// (used by xGELSD and xGESDD)
        /// =10: ieee NaN arithmetic can be trusted not to trap
        /// =11: infinity arithmetic can be trusted not to trap
        /// 12 .LE. ISPEC .LE. 16:
        /// xHSEQR or one of its subroutines,
        /// see IPARMQ for detailed explanation
        ///</param>
        /// <param name="NAME">
        /// (input) CHARACTER*(*)
        /// The name of the calling subroutine, in either upper case or
        /// lower case.
        ///</param>
        /// <param name="OPTS">
        /// (input) CHARACTER*(*)
        /// The character options to the subroutine NAME, concatenated
        /// into a single character string.  For example, UPLO = 'U',
        /// TRANS = 'T', and DIAG = 'N' for a triangular routine would
        /// be specified as OPTS = 'UTN'.
        ///</param>
        /// <param name="N1">
        /// (input) INTEGER
        ///</param>
        /// <param name="N2">
        /// (input) INTEGER
        ///</param>
        /// <param name="N3">
        /// (input) INTEGER
        ///</param>
        /// <param name="N4">
        /// (input) INTEGER
        /// Problem dimensions for the subroutine NAME; these may not all
        /// be required.
        ///</param>
        public int Run(int ISPEC, string NAME, string OPTS, int N1, int N2, int N3
                       , int N4)
        {
            int ilaenv = 0;

            #region Variables

            int    I = 0; int IC = 0; int IZ = 0; int NB = 0; int NBMIN = 0; int NX = 0; bool CNAME = false; bool SNAME = false;
            string C1 = new string(' ', 1); string C2 = new string(' ', 2); string C4 = new string(' ', 2);
            string C3 = new string(' ', 3); string SUBNAM = new string(' ', 6);

            #endregion


            #region Prolog

            // *
            // *  -- LAPACK auxiliary routine (version 3.1.1) --
            // *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
            // *     January 2007
            // *
            // *     .. Scalar Arguments ..
            // *     ..
            // *
            // *  Purpose
            // *  =======
            // *
            // *  ILAENV is called from the LAPACK routines to choose problem-dependent
            // *  parameters for the local environment.  See ISPEC for a description of
            // *  the parameters.
            // *
            // *  ILAENV returns an INTEGER
            // *  if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC
            // *  if ILAENV < 0:  if ILAENV = -k, the k-th argument had an illegal value.
            // *
            // *  This version provides a set of parameters which should give good,
            // *  but not optimal, performance on many of the currently available
            // *  computers.  Users are encouraged to modify this subroutine to set
            // *  the tuning parameters for their particular machine using the option
            // *  and problem size information in the arguments.
            // *
            // *  This routine will not function correctly if it is converted to all
            // *  lower case.  Converting it to all upper case is allowed.
            // *
            // *  Arguments
            // *  =========
            // *
            // *  ISPEC   (input) INTEGER
            // *          Specifies the parameter to be returned as the value of
            // *          ILAENV.
            // *          = 1: the optimal blocksize; if this value is 1, an unblocked
            // *               algorithm will give the best performance.
            // *          = 2: the minimum block size for which the block routine
            // *               should be used; if the usable block size is less than
            // *               this value, an unblocked routine should be used.
            // *          = 3: the crossover point (in a block routine, for N less
            // *               than this value, an unblocked routine should be used)
            // *          = 4: the number of shifts, used in the nonsymmetric
            // *               eigenvalue routines (DEPRECATED)
            // *          = 5: the minimum column dimension for blocking to be used;
            // *               rectangular blocks must have dimension at least k by m,
            // *               where k is given by ILAENV(2,...) and m by ILAENV(5,...)
            // *          = 6: the crossover point for the SVD (when reducing an m by n
            // *               matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds
            // *               this value, a QR factorization is used first to reduce
            // *               the matrix to a triangular form.)
            // *          = 7: the number of processors
            // *          = 8: the crossover point for the multishift QR method
            // *               for nonsymmetric eigenvalue problems (DEPRECATED)
            // *          = 9: maximum size of the subproblems at the bottom of the
            // *               computation tree in the divide-and-conquer algorithm
            // *               (used by xGELSD and xGESDD)
            // *          =10: ieee NaN arithmetic can be trusted not to trap
            // *          =11: infinity arithmetic can be trusted not to trap
            // *          12 <= ISPEC <= 16:
            // *               xHSEQR or one of its subroutines,
            // *               see IPARMQ for detailed explanation
            // *
            // *  NAME    (input) CHARACTER*(*)
            // *          The name of the calling subroutine, in either upper case or
            // *          lower case.
            // *
            // *  OPTS    (input) CHARACTER*(*)
            // *          The character options to the subroutine NAME, concatenated
            // *          into a single character string.  For example, UPLO = 'U',
            // *          TRANS = 'T', and DIAG = 'N' for a triangular routine would
            // *          be specified as OPTS = 'UTN'.
            // *
            // *  N1      (input) INTEGER
            // *  N2      (input) INTEGER
            // *  N3      (input) INTEGER
            // *  N4      (input) INTEGER
            // *          Problem dimensions for the subroutine NAME; these may not all
            // *          be required.
            // *
            // *  Further Details
            // *  ===============
            // *
            // *  The following conventions have been used when calling ILAENV from the
            // *  LAPACK routines:
            // *  1)  OPTS is a concatenation of all of the character options to
            // *      subroutine NAME, in the same order that they appear in the
            // *      argument list for NAME, even if they are not used in determining
            // *      the value of the parameter specified by ISPEC.
            // *  2)  The problem dimensions N1, N2, N3, N4 are specified in the order
            // *      that they appear in the argument list for NAME.  N1 is used
            // *      first, N2 second, and so on, and unused problem dimensions are
            // *      passed a value of -1.
            // *  3)  The parameter value returned by ILAENV is checked for validity in
            // *      the calling subroutine.  For example, ILAENV is used to retrieve
            // *      the optimal blocksize for STRTRI as follows:
            // *
            // *      NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 )
            // *      IF( NB.LE.1 ) NB = MAX( 1, N )
            // *
            // *  =====================================================================
            // *
            // *     .. Local Scalars ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC          CHAR, ICHAR, INT, MIN, REAL;
            // *     ..
            // *     .. External Functions ..
            // *     ..
            // *     .. Executable Statements ..
            // *

            #endregion


            #region Body

            switch (ISPEC)
            {
            case 1: goto LABEL10;

            case 2: goto LABEL10;

            case 3: goto LABEL10;

            case 4: goto LABEL80;

            case 5: goto LABEL90;

            case 6: goto LABEL100;

            case 7: goto LABEL110;

            case 8: goto LABEL120;

            case 9: goto LABEL130;

            case 10: goto LABEL140;

            case 11: goto LABEL150;

            case 12: goto LABEL160;

            case 13: goto LABEL160;

            case 14: goto LABEL160;

            case 15: goto LABEL160;

            case 16: goto LABEL160;
            }
            // *
            // *     Invalid value for ISPEC
            // *
            ilaenv = -1;
            return(ilaenv);

            // *
            LABEL10 :;
            // *
            // *     Convert NAME to upper case if the first character is lower case.
            // *
            ilaenv = 1;
            FortranLib.Copy(ref SUBNAM, NAME);
            IC = Convert.ToInt32(Convert.ToChar(FortranLib.Substring(SUBNAM, 1, 1)));
            IZ = Convert.ToInt32('Z');
            if (IZ == 90 || IZ == 122)
            {
                // *
                // *        ASCII character set
                // *
                if (IC >= 97 && IC <= 122)
                {
                    FortranLib.Copy(ref SUBNAM, 1, 1, Convert.ToChar(IC - 32));
                    for (I = 2; I <= 6; I++)
                    {
                        IC = Convert.ToInt32(Convert.ToChar(FortranLib.Substring(SUBNAM, I, I)));
                        if (IC >= 97 && IC <= 122)
                        {
                            FortranLib.Copy(ref SUBNAM, I, I, Convert.ToChar(IC - 32));
                        }
                    }
                }
                // *
            }
            else
            {
                if (IZ == 233 || IZ == 169)
                {
                    // *
                    // *        EBCDIC character set
                    // *
                    if ((IC >= 129 && IC <= 137) || (IC >= 145 && IC <= 153) || (IC >= 162 && IC <= 169))
                    {
                        FortranLib.Copy(ref SUBNAM, 1, 1, Convert.ToChar(IC + 64));
                        for (I = 2; I <= 6; I++)
                        {
                            IC = Convert.ToInt32(Convert.ToChar(FortranLib.Substring(SUBNAM, I, I)));
                            if ((IC >= 129 && IC <= 137) || (IC >= 145 && IC <= 153) || (IC >= 162 && IC <= 169))
                            {
                                FortranLib.Copy(ref SUBNAM, I, I, Convert.ToChar(IC + 64));
                            }
                        }
                    }
                    // *
                }
                else
                {
                    if (IZ == 218 || IZ == 250)
                    {
                        // *
                        // *        Prime machines:  ASCII+128
                        // *
                        if (IC >= 225 && IC <= 250)
                        {
                            FortranLib.Copy(ref SUBNAM, 1, 1, Convert.ToChar(IC - 32));
                            for (I = 2; I <= 6; I++)
                            {
                                IC = Convert.ToInt32(Convert.ToChar(FortranLib.Substring(SUBNAM, I, I)));
                                if (IC >= 225 && IC <= 250)
                                {
                                    FortranLib.Copy(ref SUBNAM, I, I, Convert.ToChar(IC - 32));
                                }
                            }
                        }
                    }
                }
            }
            // *
            FortranLib.Copy(ref C1, FortranLib.Substring(SUBNAM, 1, 1));
            SNAME = C1 == "S" || C1 == "D";
            CNAME = C1 == "C" || C1 == "Z";
            if (!(CNAME || SNAME))
            {
                return(ilaenv);
            }
            FortranLib.Copy(ref C2, FortranLib.Substring(SUBNAM, 2, 3));
            FortranLib.Copy(ref C3, FortranLib.Substring(SUBNAM, 4, 6));
            FortranLib.Copy(ref C4, FortranLib.Substring(C3, 2, 3));
            // *
            switch (ISPEC)
            {
            case 1: goto LABEL50;

            case 2: goto LABEL60;

            case 3: goto LABEL70;
            }
            // *
            LABEL50 :;
            // *
            // *     ISPEC = 1:  block size
            // *
            // *     In these examples, separate code is provided for setting NB for
            // *     real and complex.  We assume that NB will take the same value in
            // *     single or double precision.
            // *
            NB = 1;
            // *
            if (C2 == "GE")
            {
                if (C3 == "TRF")
                {
                    if (SNAME)
                    {
                        NB = 64;
                    }
                    else
                    {
                        NB = 64;
                    }
                }
                else
                {
                    if (C3 == "QRF" || C3 == "RQF" || C3 == "LQF" || C3 == "QLF")
                    {
                        if (SNAME)
                        {
                            NB = 32;
                        }
                        else
                        {
                            NB = 32;
                        }
                    }
                    else
                    {
                        if (C3 == "HRD")
                        {
                            if (SNAME)
                            {
                                NB = 32;
                            }
                            else
                            {
                                NB = 32;
                            }
                        }
                        else
                        {
                            if (C3 == "BRD")
                            {
                                if (SNAME)
                                {
                                    NB = 32;
                                }
                                else
                                {
                                    NB = 32;
                                }
                            }
                            else
                            {
                                if (C3 == "TRI")
                                {
                                    if (SNAME)
                                    {
                                        NB = 64;
                                    }
                                    else
                                    {
                                        NB = 64;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                if (C2 == "PO")
                {
                    if (C3 == "TRF")
                    {
                        if (SNAME)
                        {
                            NB = 64;
                        }
                        else
                        {
                            NB = 64;
                        }
                    }
                }
                else
                {
                    if (C2 == "SY")
                    {
                        if (C3 == "TRF")
                        {
                            if (SNAME)
                            {
                                NB = 64;
                            }
                            else
                            {
                                NB = 64;
                            }
                        }
                        else
                        {
                            if (SNAME && C3 == "TRD")
                            {
                                NB = 32;
                            }
                            else
                            {
                                if (SNAME && C3 == "GST")
                                {
                                    NB = 64;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (CNAME && C2 == "HE")
                        {
                            if (C3 == "TRF")
                            {
                                NB = 64;
                            }
                            else
                            {
                                if (C3 == "TRD")
                                {
                                    NB = 32;
                                }
                                else
                                {
                                    if (C3 == "GST")
                                    {
                                        NB = 64;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (SNAME && C2 == "OR")
                            {
                                if (FortranLib.Substring(C3, 1, 1) == "G")
                                {
                                    if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                    {
                                        NB = 32;
                                    }
                                }
                                else
                                {
                                    if (FortranLib.Substring(C3, 1, 1) == "M")
                                    {
                                        if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                        {
                                            NB = 32;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if (CNAME && C2 == "UN")
                                {
                                    if (FortranLib.Substring(C3, 1, 1) == "G")
                                    {
                                        if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                        {
                                            NB = 32;
                                        }
                                    }
                                    else
                                    {
                                        if (FortranLib.Substring(C3, 1, 1) == "M")
                                        {
                                            if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                            {
                                                NB = 32;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    if (C2 == "GB")
                                    {
                                        if (C3 == "TRF")
                                        {
                                            if (SNAME)
                                            {
                                                if (N4 <= 64)
                                                {
                                                    NB = 1;
                                                }
                                                else
                                                {
                                                    NB = 32;
                                                }
                                            }
                                            else
                                            {
                                                if (N4 <= 64)
                                                {
                                                    NB = 1;
                                                }
                                                else
                                                {
                                                    NB = 32;
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (C2 == "PB")
                                        {
                                            if (C3 == "TRF")
                                            {
                                                if (SNAME)
                                                {
                                                    if (N2 <= 64)
                                                    {
                                                        NB = 1;
                                                    }
                                                    else
                                                    {
                                                        NB = 32;
                                                    }
                                                }
                                                else
                                                {
                                                    if (N2 <= 64)
                                                    {
                                                        NB = 1;
                                                    }
                                                    else
                                                    {
                                                        NB = 32;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (C2 == "TR")
                                            {
                                                if (C3 == "TRI")
                                                {
                                                    if (SNAME)
                                                    {
                                                        NB = 64;
                                                    }
                                                    else
                                                    {
                                                        NB = 64;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                if (C2 == "LA")
                                                {
                                                    if (C3 == "UUM")
                                                    {
                                                        if (SNAME)
                                                        {
                                                            NB = 64;
                                                        }
                                                        else
                                                        {
                                                            NB = 64;
                                                        }
                                                    }
                                                }
                                                else
                                                {
                                                    if (SNAME && C2 == "ST")
                                                    {
                                                        if (C3 == "EBZ")
                                                        {
                                                            NB = 1;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            ilaenv = NB;
            return(ilaenv);

            // *
            LABEL60 :;
            // *
            // *     ISPEC = 2:  minimum block size
            // *
            NBMIN = 2;
            if (C2 == "GE")
            {
                if (C3 == "QRF" || C3 == "RQF" || C3 == "LQF" || C3 == "QLF")
                {
                    if (SNAME)
                    {
                        NBMIN = 2;
                    }
                    else
                    {
                        NBMIN = 2;
                    }
                }
                else
                {
                    if (C3 == "HRD")
                    {
                        if (SNAME)
                        {
                            NBMIN = 2;
                        }
                        else
                        {
                            NBMIN = 2;
                        }
                    }
                    else
                    {
                        if (C3 == "BRD")
                        {
                            if (SNAME)
                            {
                                NBMIN = 2;
                            }
                            else
                            {
                                NBMIN = 2;
                            }
                        }
                        else
                        {
                            if (C3 == "TRI")
                            {
                                if (SNAME)
                                {
                                    NBMIN = 2;
                                }
                                else
                                {
                                    NBMIN = 2;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                if (C2 == "SY")
                {
                    if (C3 == "TRF")
                    {
                        if (SNAME)
                        {
                            NBMIN = 8;
                        }
                        else
                        {
                            NBMIN = 8;
                        }
                    }
                    else
                    {
                        if (SNAME && C3 == "TRD")
                        {
                            NBMIN = 2;
                        }
                    }
                }
                else
                {
                    if (CNAME && C2 == "HE")
                    {
                        if (C3 == "TRD")
                        {
                            NBMIN = 2;
                        }
                    }
                    else
                    {
                        if (SNAME && C2 == "OR")
                        {
                            if (FortranLib.Substring(C3, 1, 1) == "G")
                            {
                                if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                {
                                    NBMIN = 2;
                                }
                            }
                            else
                            {
                                if (FortranLib.Substring(C3, 1, 1) == "M")
                                {
                                    if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                    {
                                        NBMIN = 2;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (CNAME && C2 == "UN")
                            {
                                if (FortranLib.Substring(C3, 1, 1) == "G")
                                {
                                    if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                    {
                                        NBMIN = 2;
                                    }
                                }
                                else
                                {
                                    if (FortranLib.Substring(C3, 1, 1) == "M")
                                    {
                                        if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                        {
                                            NBMIN = 2;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            ilaenv = NBMIN;
            return(ilaenv);

            // *
            LABEL70 :;
            // *
            // *     ISPEC = 3:  crossover point
            // *
            NX = 0;
            if (C2 == "GE")
            {
                if (C3 == "QRF" || C3 == "RQF" || C3 == "LQF" || C3 == "QLF")
                {
                    if (SNAME)
                    {
                        NX = 128;
                    }
                    else
                    {
                        NX = 128;
                    }
                }
                else
                {
                    if (C3 == "HRD")
                    {
                        if (SNAME)
                        {
                            NX = 128;
                        }
                        else
                        {
                            NX = 128;
                        }
                    }
                    else
                    {
                        if (C3 == "BRD")
                        {
                            if (SNAME)
                            {
                                NX = 128;
                            }
                            else
                            {
                                NX = 128;
                            }
                        }
                    }
                }
            }
            else
            {
                if (C2 == "SY")
                {
                    if (SNAME && C3 == "TRD")
                    {
                        NX = 32;
                    }
                }
                else
                {
                    if (CNAME && C2 == "HE")
                    {
                        if (C3 == "TRD")
                        {
                            NX = 32;
                        }
                    }
                    else
                    {
                        if (SNAME && C2 == "OR")
                        {
                            if (FortranLib.Substring(C3, 1, 1) == "G")
                            {
                                if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                {
                                    NX = 128;
                                }
                            }
                        }
                        else
                        {
                            if (CNAME && C2 == "UN")
                            {
                                if (FortranLib.Substring(C3, 1, 1) == "G")
                                {
                                    if (C4 == "QR" || C4 == "RQ" || C4 == "LQ" || C4 == "QL" || C4 == "HR" || C4 == "TR" || C4 == "BR")
                                    {
                                        NX = 128;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            ilaenv = NX;
            return(ilaenv);

            // *
            LABEL80 :;
            // *
            // *     ISPEC = 4:  number of shifts (used by xHSEQR)
            // *
            ilaenv = 6;
            return(ilaenv);

            // *
            LABEL90 :;
            // *
            // *     ISPEC = 5:  minimum column dimension (not used)
            // *
            ilaenv = 2;
            return(ilaenv);

            // *
            LABEL100 :;
            // *
            // *     ISPEC = 6:  crossover point for SVD (used by xGELSS and xGESVD)
            // *
            ilaenv = Convert.ToInt32(Math.Truncate(Convert.ToSingle(Math.Min(N1, N2)) * 1.6E0));
            return(ilaenv);

            // *
            LABEL110 :;
            // *
            // *     ISPEC = 7:  number of processors (not used)
            // *
            ilaenv = 1;
            return(ilaenv);

            // *
            LABEL120 :;
            // *
            // *     ISPEC = 8:  crossover point for multishift (used by xHSEQR)
            // *
            ilaenv = 50;
            return(ilaenv);

            // *
            LABEL130 :;
            // *
            // *     ISPEC = 9:  maximum size of the subproblems at the bottom of the
            // *                 computation tree in the divide-and-conquer algorithm
            // *                 (used by xGELSD and xGESDD)
            // *
            ilaenv = 25;
            return(ilaenv);

            // *
            LABEL140 :;
            // *
            // *     ISPEC = 10: ieee NaN arithmetic can be trusted not to trap
            // *
            // *     ILAENV = 0
            ilaenv = 1;
            if (ilaenv == 1)
            {
                ilaenv = this._ieeeck.Run(0, 0.0, 1.0);
            }
            return(ilaenv);

            // *
            LABEL150 :;
            // *
            // *     ISPEC = 11: infinity arithmetic can be trusted not to trap
            // *
            // *     ILAENV = 0
            ilaenv = 1;
            if (ilaenv == 1)
            {
                ilaenv = this._ieeeck.Run(1, 0.0, 1.0);
            }
            return(ilaenv);

            // *
            LABEL160 :;
            // *
            // *     12 <= ISPEC <= 16: xHSEQR or one of its subroutines.
            // *
            ilaenv = this._iparmq.Run(ISPEC, NAME, OPTS, N1, N2, N3, N4);
            return(ilaenv);

            // *
            // *     End of ILAENV
            // *

            #endregion
        }
Beispiel #2
0
        /// <summary>
        /// Purpose
        /// =======
        ///
        /// DHSEQR 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="JOB">
        /// (input) CHARACTER*1
        /// = 'E':  compute eigenvalues only;
        /// = 'S':  compute eigenvalues and the Schur form T.
        ///</param>
        /// <param name="COMPZ">
        /// (input) CHARACTER*1
        /// = 'N':  no Schur vectors are computed;
        /// = 'I':  Z is initialized to the unit matrix and the matrix Z
        /// of Schur vectors of H is returned;
        /// = 'V':  Z must contain an orthogonal matrix Q on entry, and
        /// the product Q*Z is returned.
        ///</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. 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 JOB = 'S', 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 JOB = 'E', 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.)
        ///
        /// Unlike earlier versions of DHSEQR, this subroutine may
        /// explicitly 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 (N)
        ///</param>
        /// <param name="WI">
        /// (output) DOUBLE PRECISION array, dimension (N)
        /// The real and imaginary parts, respectively, of the computed
        /// eigenvalues. 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 JOB = 'S', 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="Z">
        /// (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
        /// If COMPZ = 'N', Z is not referenced.
        /// If COMPZ = 'I', on entry Z need not be set and on exit,
        /// if INFO = 0, Z contains the orthogonal matrix Z of the Schur
        /// vectors of H.  If COMPZ = 'V', on entry Z must contain an
        /// N-by-N matrix Q, which is assumed to be equal to the unit
        /// matrix except for the submatrix Z(ILO:IHI,ILO:IHI). On exit,
        /// if INFO = 0, Z contains Q*Z.
        /// Normally Q is the orthogonal matrix generated by DORGHR
        /// after the call to DGEHRD which formed the Hessenberg matrix
        /// H. (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 COMPZ = 'I' or
        /// COMPZ = 'V', then LDZ.GE.MAX(1,N).  Otherwize, LDZ.GE.1.
        ///</param>
        /// <param name="WORK">
        /// (workspace/output) DOUBLE PRECISION array, dimension (LWORK)
        /// On exit, if INFO = 0, 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 DHSEQR does a workspace query.
        /// In this case, DHSEQR 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
        /// .LT. 0:  if INFO = -i, the i-th argument had an illegal
        /// value
        /// .GT. 0:  if INFO = i, DHSEQR 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 JOB = 'E', 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 JOB   = 'S', 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 COMPZ = 'V', then on exit
        ///
        /// (final value of Z)  =  (initial value of Z)*U
        ///
        /// where U is the orthogonal matrix in (*) (regard-
        /// less of the value of JOB.)
        ///
        /// If INFO .GT. 0 and COMPZ = 'I', then on exit
        /// (final value of Z)  = U
        /// where U is the orthogonal matrix in (*) (regard-
        /// less of the value of JOB.)
        ///
        /// If INFO .GT. 0 and COMPZ = 'N', then Z is not
        /// accessed.
        ///</param>
        public void Run(string JOB, string COMPZ, 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, ref double[] Z, int offset_z, int LDZ, ref double[] WORK, int offset_work
                        , int LWORK, ref int INFO)
        {
            #region Variables

            int  offset_hl = 0; int o_hl = -1 - NL; int offset_workl = 0; int I = 0; int KBOT = 0; int NMIN = 0;
            bool INITZ = false; bool LQUERY = false; bool WANTT = false; bool WANTZ = false;

            #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 Strings

            JOB = JOB.Substring(0, 1);  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
            // *     =======
            // *
            // *     DHSEQR 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
            // *     =========
            // *
            // *     JOB   (input) CHARACTER*1
            // *           = 'E':  compute eigenvalues only;
            // *           = 'S':  compute eigenvalues and the Schur form T.
            // *
            // *     COMPZ (input) CHARACTER*1
            // *           = 'N':  no Schur vectors are computed;
            // *           = 'I':  Z is initialized to the unit matrix and the matrix Z
            // *                   of Schur vectors of H is returned;
            // *           = 'V':  Z must contain an orthogonal matrix Q on entry, and
            // *                   the product Q*Z is returned.
            // *
            // *     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. 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 JOB = 'S', 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 JOB = 'E', 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.)
            // *
            // *           Unlike earlier versions of DHSEQR, this subroutine may
            // *           explicitly 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 (N)
            // *     WI    (output) DOUBLE PRECISION array, dimension (N)
            // *           The real and imaginary parts, respectively, of the computed
            // *           eigenvalues. 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 JOB = 'S', 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).
            // *
            // *     Z     (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
            // *           If COMPZ = 'N', Z is not referenced.
            // *           If COMPZ = 'I', on entry Z need not be set and on exit,
            // *           if INFO = 0, Z contains the orthogonal matrix Z of the Schur
            // *           vectors of H.  If COMPZ = 'V', on entry Z must contain an
            // *           N-by-N matrix Q, which is assumed to be equal to the unit
            // *           matrix except for the submatrix Z(ILO:IHI,ILO:IHI). On exit,
            // *           if INFO = 0, Z contains Q*Z.
            // *           Normally Q is the orthogonal matrix generated by DORGHR
            // *           after the call to DGEHRD which formed the Hessenberg matrix
            // *           H. (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 COMPZ = 'I' or
            // *           COMPZ = 'V', then LDZ.GE.MAX(1,N).  Otherwize, LDZ.GE.1.
            // *
            // *     WORK  (workspace/output) DOUBLE PRECISION array, dimension (LWORK)
            // *           On exit, if INFO = 0, 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 DHSEQR does a workspace query.
            // *           In this case, DHSEQR 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
            // *           .LT. 0:  if INFO = -i, the i-th argument had an illegal
            // *                    value
            // *           .GT. 0:  if INFO = i, DHSEQR 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 JOB = 'E', 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 JOB   = 'S', 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 COMPZ = 'V', then on exit
            // *
            // *                  (final value of Z)  =  (initial value of Z)*U
            // *
            // *                where U is the orthogonal matrix in (*) (regard-
            // *                less of the value of JOB.)
            // *
            // *                If INFO .GT. 0 and COMPZ = 'I', then on exit
            // *                      (final value of Z)  = U
            // *                where U is the orthogonal matrix in (*) (regard-
            // *                less of the value of JOB.)
            // *
            // *                If INFO .GT. 0 and COMPZ = 'N', then Z is not
            // *                accessed.
            // *
            // *     ================================================================
            // *             Default values supplied by
            // *             ILAENV(ISPEC,'DHSEQR',JOB(:1)//COMPZ(:1),N,ILO,IHI,LWORK).
            // *             It is suggested that these defaults be adjusted in order
            // *             to attain best performance in each particular
            // *             computational environment.
            // *
            // *            ISPEC=1:  The DLAHQR vs DLAQR0 crossover point.
            // *                      Default: 75. (Must be at least 11.)
            // *
            // *            ISPEC=2:  Recommended deflation window size.
            // *                      This depends on ILO, IHI and NS.  NS is the
            // *                      number of simultaneous shifts returned
            // *                      by ILAENV(ISPEC=4).  (See ISPEC=4 below.)
            // *                      The default for (IHI-ILO+1).LE.500 is NS.
            // *                      The default for (IHI-ILO+1).GT.500 is 3*NS/2.
            // *
            // *            ISPEC=3:  Nibble crossover point. (See ILAENV for
            // *                      details.)  Default: 14% of deflation window
            // *                      size.
            // *
            // *            ISPEC=4:  Number of simultaneous shifts, NS, in
            // *                      a multi-shift QR iteration.
            // *
            // *                      If IHI-ILO+1 is ...
            // *
            // *                      greater than      ...but less    ... the
            // *                      or equal to ...      than        default is
            // *
            // *                           1               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 some or all matrices of this order
            // *                       are passed to the implicit double shift routine
            // *                       DLAHQR and NS is ignored.  See ISPEC=1 above
            // *                       and comments in IPARM for details.
            // *
            // *                       The asterisks (**) indicate an ad-hoc
            // *                       function of N increasing from 10 to 64.
            // *
            // *            ISPEC=5:  Select structured matrix multiply.
            // *                      (See ILAENV for details.) Default: 3.
            // *
            // *     ================================================================
            // *     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.) ====
            // *
            // *     ==== NL allocates some local workspace to help small matrices
            // *     .    through a rare DLAHQR failure.  NL .GT. NTINY = 11 is
            // *     .    required and NL .LE. NMIN = ILAENV(ISPEC=1,...) is recom-
            // *     .    mended.  (The default value of NMIN is 75.)  Using NL = 49
            // *     .    allows up to six simultaneous shifts and a 16-by-16
            // *     .    deflation window.  ====
            // *
            // *     ..
            // *     .. Local Arrays ..
            // *     ..
            // *     .. Local Scalars ..
            // *     ..
            // *     .. External Functions ..
            // *     ..
            // *     .. External Subroutines ..
            // *     ..
            // *     .. Intrinsic Functions ..
            //      INTRINSIC          DBLE, MAX, MIN;
            // *     ..
            // *     .. Executable Statements ..
            // *
            // *     ==== Decode and check the input parameters. ====
            // *

            #endregion


            #region Body

            WANTT            = this._lsame.Run(JOB, "S");
            INITZ            = this._lsame.Run(COMPZ, "I");
            WANTZ            = INITZ || this._lsame.Run(COMPZ, "V");
            WORK[1 + o_work] = Convert.ToDouble(Math.Max(1, N));
            LQUERY           = LWORK == -1;
            // *
            INFO = 0;
            if (!this._lsame.Run(JOB, "E") && !WANTT)
            {
                INFO = -1;
            }
            else
            {
                if (!this._lsame.Run(COMPZ, "N") && !WANTZ)
                {
                    INFO = -2;
                }
                else
                {
                    if (N < 0)
                    {
                        INFO = -3;
                    }
                    else
                    {
                        if (ILO < 1 || ILO > Math.Max(1, N))
                        {
                            INFO = -4;
                        }
                        else
                        {
                            if (IHI < Math.Min(ILO, N) || IHI > N)
                            {
                                INFO = -5;
                            }
                            else
                            {
                                if (LDH < Math.Max(1, N))
                                {
                                    INFO = -7;
                                }
                                else
                                {
                                    if (LDZ < 1 || (WANTZ && LDZ < Math.Max(1, N)))
                                    {
                                        INFO = -11;
                                    }
                                    else
                                    {
                                        if (LWORK < Math.Max(1, N) && !LQUERY)
                                        {
                                            INFO = -13;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // *
            if (INFO != 0)
            {
                // *
                // *        ==== Quick return in case of invalid argument. ====
                // *
                this._xerbla.Run("DHSEQR", -INFO);
                return;
                // *
            }
            else
            {
                if (N == 0)
                {
                    // *
                    // *        ==== Quick return in case N = 0; nothing to do. ====
                    // *
                    return;
                    // *
                }
                else
                {
                    if (LQUERY)
                    {
                        // *
                        // *        ==== Quick return in case of a workspace query ====
                        // *
                        this._dlaqr0.Run(WANTT, WANTZ, N, ILO, IHI, ref H, offset_h
                                         , LDH, ref WR, offset_wr, ref WI, offset_wi, ILO, IHI, ref Z, offset_z
                                         , LDZ, ref WORK, offset_work, LWORK, ref INFO);
                        // *        ==== Ensure reported workspace size is backward-compatible with
                        // *        .    previous LAPACK versions. ====
                        WORK[1 + o_work] = Math.Max(Convert.ToDouble(Math.Max(1, N)), WORK[1 + o_work]);
                        return;
                        // *
                    }
                    else
                    {
                        // *
                        // *        ==== copy eigenvalues isolated by DGEBAL ====
                        // *
                        for (I = 1; I <= ILO - 1; I++)
                        {
                            WR[I + o_wr] = H[I + I * LDH + o_h];
                            WI[I + o_wi] = ZERO;
                        }
                        for (I = IHI + 1; I <= N; I++)
                        {
                            WR[I + o_wr] = H[I + I * LDH + o_h];
                            WI[I + o_wi] = ZERO;
                        }
                        // *
                        // *        ==== Initialize Z, if requested ====
                        // *
                        if (INITZ)
                        {
                            this._dlaset.Run("A", N, N, ZERO, ONE, ref Z, offset_z
                                             , LDZ);
                        }
                        // *
                        // *        ==== Quick return if possible ====
                        // *
                        if (ILO == IHI)
                        {
                            WR[ILO + o_wr] = H[ILO + ILO * LDH + o_h];
                            WI[ILO + o_wi] = ZERO;
                            return;
                        }
                        // *
                        // *        ==== DLAHQR/DLAQR0 crossover point ====
                        // *
                        NMIN = this._ilaenv.Run(12, "DHSEQR", FortranLib.Substring(JOB, 1, 1) + FortranLib.Substring(COMPZ, 1, 1), N, ILO, IHI, LWORK);
                        NMIN = Math.Max(NTINY, NMIN);
                        // *
                        // *        ==== DLAQR0 for big matrices; DLAHQR for small ones ====
                        // *
                        if (N > NMIN)
                        {
                            this._dlaqr0.Run(WANTT, WANTZ, N, ILO, IHI, ref H, offset_h
                                             , LDH, ref WR, offset_wr, ref WI, offset_wi, ILO, IHI, ref Z, offset_z
                                             , LDZ, ref WORK, offset_work, LWORK, ref INFO);
                        }
                        else
                        {
                            // *
                            // *           ==== Small matrix ====
                            // *
                            this._dlahqr.Run(WANTT, WANTZ, N, ILO, IHI, ref H, offset_h
                                             , LDH, ref WR, offset_wr, ref WI, offset_wi, ILO, IHI, ref Z, offset_z
                                             , LDZ, ref INFO);
                            // *
                            if (INFO > 0)
                            {
                                // *
                                // *              ==== A rare DLAHQR failure!  DLAQR0 sometimes succeeds
                                // *              .    when DLAHQR fails. ====
                                // *
                                KBOT = INFO;
                                // *
                                if (N >= NL)
                                {
                                    // *
                                    // *                 ==== Larger matrices have enough subdiagonal scratch
                                    // *                 .    space to call DLAQR0 directly. ====
                                    // *
                                    this._dlaqr0.Run(WANTT, WANTZ, N, ILO, KBOT, ref H, offset_h
                                                     , LDH, ref WR, offset_wr, ref WI, offset_wi, ILO, IHI, ref Z, offset_z
                                                     , LDZ, ref WORK, offset_work, LWORK, ref INFO);
                                    // *
                                }
                                else
                                {
                                    // *
                                    // *                 ==== Tiny matrices don't have enough subdiagonal
                                    // *                 .    scratch space to benefit from DLAQR0.  Hence,
                                    // *                 .    tiny matrices must be copied into a larger
                                    // *                 .    array before calling DLAQR0. ====
                                    // *
                                    this._dlacpy.Run("A", N, N, H, offset_h, LDH, ref HL, offset_hl
                                                     , NL);
                                    HL[N + 1 + N * NL + o_hl] = ZERO;
                                    this._dlaset.Run("A", NL, NL - N, ZERO, ZERO, ref HL, 1 + (N + 1) * NL + o_hl
                                                     , NL);
                                    this._dlaqr0.Run(WANTT, WANTZ, NL, ILO, KBOT, ref HL, offset_hl
                                                     , NL, ref WR, offset_wr, ref WI, offset_wi, ILO, IHI, ref Z, offset_z
                                                     , LDZ, ref WORKL, offset_workl, NL, ref INFO);
                                    if (WANTT || INFO != 0)
                                    {
                                        this._dlacpy.Run("A", N, N, HL, offset_hl, NL, ref H, offset_h
                                                         , LDH);
                                    }
                                }
                            }
                        }
                        // *
                        // *        ==== Clear out the trash, if necessary. ====
                        // *
                        if ((WANTT || INFO != 0) && N > 2)
                        {
                            this._dlaset.Run("L", N - 2, N - 2, ZERO, ZERO, ref H, 3 + 1 * LDH + o_h
                                             , LDH);
                        }
                        // *
                        // *        ==== Ensure reported workspace size is backward-compatible with
                        // *        .    previous LAPACK versions. ====
                        // *
                        WORK[1 + o_work] = Math.Max(Convert.ToDouble(Math.Max(1, N)), WORK[1 + o_work]);
                    }
                }
            }
            // *
            // *     ==== End of DHSEQR ====
            // *

            #endregion
        }