コード例 #1
0
ファイル: matinv.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Inversion of a matrix given by its LU decomposition.

        INPUT PARAMETERS:
            A       -   LU decomposition of the matrix (output of CMatrixLU subroutine).
            Pivots  -   table of permutations which were made during the LU decomposition
                        (the output of CMatrixLU subroutine).
            N       -   size of matrix A.

        OUTPUT PARAMETERS:
            Info    -   return code, same as in RMatrixLUInverse
            Rep     -   solver report, same as in RMatrixLUInverse
            A       -   inverse of matrix A, same as in RMatrixLUInverse

          -- ALGLIB routine --
             05.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixluinverse(ref AP.Complex[,] a,
            ref int[] pivots,
            int n,
            ref int info,
            ref matinvreport rep)
        {
            AP.Complex[] work = new AP.Complex[0];
            int i = 0;
            int j = 0;
            int k = 0;
            AP.Complex v = 0;

            info = 1;

            //
            // Quick return if possible
            //
            if (n == 0)
            {
                info = -1;
                return;
            }
            for (i = 0; i <= n - 1; i++)
            {
                if (pivots[i] > n - 1 | pivots[i] < i)
                {
                    info = -1;
                    return;
                }
            }

            //
            // calculate condition numbers
            //
            rep.r1 = rcond.cmatrixlurcond1(ref a, n);
            rep.rinf = rcond.cmatrixlurcondinf(ref a, n);
            if ((double)(rep.r1) < (double)(rcond.rcondthreshold()) | (double)(rep.rinf) < (double)(rcond.rcondthreshold()))
            {
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        a[i, j] = 0;
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }

            //
            // Call cache-oblivious code
            //
            work = new AP.Complex[n];
            cmatrixluinverserec(ref a, 0, n, ref work, ref info, ref rep);

            //
            // apply permutations
            //
            for (i = 0; i <= n - 1; i++)
            {
                for (j = n - 2; j >= 0; j--)
                {
                    k = pivots[j];
                    v = a[i, j];
                    a[i, j] = a[i, k];
                    a[i, k] = v;
                }
            }
        }
コード例 #2
0
ファイル: rcond.cs プロジェクト: mortenbakkedal/SharpMath
        private static void cmatrixestimatenorm(int n,
            ref AP.Complex[] v,
            ref AP.Complex[] x,
            ref double est,
            ref int kase,
            ref int[] isave,
            ref double[] rsave)
        {
            int itmax = 0;
            int i = 0;
            int iter = 0;
            int j = 0;
            int jlast = 0;
            int jump = 0;
            double absxi = 0;
            double altsgn = 0;
            double estold = 0;
            double safmin = 0;
            double temp = 0;
            int i_ = 0;


            //
            //Executable Statements ..
            //
            itmax = 5;
            safmin = AP.Math.MinRealNumber;
            if (kase == 0)
            {
                v = new AP.Complex[n + 1];
                x = new AP.Complex[n + 1];
                isave = new int[5];
                rsave = new double[4];
                for (i = 1; i <= n; i++)
                {
                    x[i] = (double)(1) / (double)(n);
                }
                kase = 1;
                jump = 1;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }
            internalcomplexrcondloadall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);

            //
            // ENTRY   (JUMP = 1)
            // FIRST ITERATION.  X HAS BEEN OVERWRITTEN BY A*X.
            //
            if (jump == 1)
            {
                if (n == 1)
                {
                    v[1] = x[1];
                    est = AP.Math.AbsComplex(v[1]);
                    kase = 0;
                    internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                    return;
                }
                est = internalcomplexrcondscsum1(ref x, n);
                for (i = 1; i <= n; i++)
                {
                    absxi = AP.Math.AbsComplex(x[i]);
                    if ((double)(absxi) > (double)(safmin))
                    {
                        x[i] = x[i] / absxi;
                    }
                    else
                    {
                        x[i] = 1;
                    }
                }
                kase = 2;
                jump = 2;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }

            //
            // ENTRY   (JUMP = 2)
            // FIRST ITERATION.  X HAS BEEN OVERWRITTEN BY CTRANS(A)*X.
            //
            if (jump == 2)
            {
                j = internalcomplexrcondicmax1(ref x, n);
                iter = 2;

                //
                // MAIN LOOP - ITERATIONS 2,3,...,ITMAX.
                //
                for (i = 1; i <= n; i++)
                {
                    x[i] = 0;
                }
                x[j] = 1;
                kase = 1;
                jump = 3;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }

            //
            // ENTRY   (JUMP = 3)
            // X HAS BEEN OVERWRITTEN BY A*X.
            //
            if (jump == 3)
            {
                for (i_ = 1; i_ <= n; i_++)
                {
                    v[i_] = x[i_];
                }
                estold = est;
                est = internalcomplexrcondscsum1(ref v, n);

                //
                // TEST FOR CYCLING.
                //
                if ((double)(est) <= (double)(estold))
                {

                    //
                    // ITERATION COMPLETE.  FINAL STAGE.
                    //
                    altsgn = 1;
                    for (i = 1; i <= n; i++)
                    {
                        x[i] = altsgn * (1 + ((double)(i - 1)) / ((double)(n - 1)));
                        altsgn = -altsgn;
                    }
                    kase = 1;
                    jump = 5;
                    internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                    return;
                }
                for (i = 1; i <= n; i++)
                {
                    absxi = AP.Math.AbsComplex(x[i]);
                    if ((double)(absxi) > (double)(safmin))
                    {
                        x[i] = x[i] / absxi;
                    }
                    else
                    {
                        x[i] = 1;
                    }
                }
                kase = 2;
                jump = 4;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }

            //
            // ENTRY   (JUMP = 4)
            // X HAS BEEN OVERWRITTEN BY CTRANS(A)*X.
            //
            if (jump == 4)
            {
                jlast = j;
                j = internalcomplexrcondicmax1(ref x, n);
                if ((double)(AP.Math.AbsComplex(x[jlast])) != (double)(AP.Math.AbsComplex(x[j])) & iter < itmax)
                {
                    iter = iter + 1;

                    //
                    // MAIN LOOP - ITERATIONS 2,3,...,ITMAX.
                    //
                    for (i = 1; i <= n; i++)
                    {
                        x[i] = 0;
                    }
                    x[j] = 1;
                    kase = 1;
                    jump = 3;
                    internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                    return;
                }

                //
                // ITERATION COMPLETE.  FINAL STAGE.
                //
                altsgn = 1;
                for (i = 1; i <= n; i++)
                {
                    x[i] = altsgn * (1 + ((double)(i - 1)) / ((double)(n - 1)));
                    altsgn = -altsgn;
                }
                kase = 1;
                jump = 5;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }

            //
            // ENTRY   (JUMP = 5)
            // X HAS BEEN OVERWRITTEN BY A*X.
            //
            if (jump == 5)
            {
                temp = 2 * (internalcomplexrcondscsum1(ref x, n) / (3 * n));
                if ((double)(temp) > (double)(est))
                {
                    for (i_ = 1; i_ <= n; i_++)
                    {
                        v[i_] = x[i_];
                    }
                    est = temp;
                }
                kase = 0;
                internalcomplexrcondsaveall(ref isave, ref rsave, ref i, ref iter, ref j, ref jlast, ref jump, ref absxi, ref altsgn, ref estold, ref temp);
                return;
            }
        }
コード例 #3
0
ファイル: evd.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Finding the eigenvalues and eigenvectors of a Hermitian matrix

        The algorithm finds eigen pairs of a Hermitian matrix by  reducing  it  to
        real tridiagonal form and using the QL/QR algorithm.

        Input parameters:
            A       -   Hermitian matrix which is given  by  its  upper  or  lower
                        triangular part.
                        Array whose indexes range within [0..N-1, 0..N-1].
            N       -   size of matrix A.
            IsUpper -   storage format.
            ZNeeded -   flag controlling whether the eigenvectors  are  needed  or
                        not. If ZNeeded is equal to:
                         * 0, the eigenvectors are not returned;
                         * 1, the eigenvectors are returned.

        Output parameters:
            D       -   eigenvalues in ascending order.
                        Array whose index ranges within [0..N-1].
            Z       -   if ZNeeded is equal to:
                         * 0, Z hasn�t changed;
                         * 1, Z contains the eigenvectors.
                        Array whose indexes range within [0..N-1, 0..N-1].
                        The eigenvectors are stored in the matrix columns.

        Result:
            True, if the algorithm has converged.
            False, if the algorithm hasn't converged (rare case).

        Note:
            eigenvectors of Hermitian matrix are defined up to  multiplication  by
            a complex number L, such that |L|=1.

          -- ALGLIB --
             Copyright 2005, 23 March 2007 by Bochkanov Sergey
        *************************************************************************/
        public static bool hmatrixevd(AP.Complex[,] a,
            int n,
            int zneeded,
            bool isupper,
            ref double[] d,
            ref AP.Complex[,] z)
        {
            bool result = new bool();
            AP.Complex[] tau = new AP.Complex[0];
            double[] e = new double[0];
            double[] work = new double[0];
            double[,] t = new double[0, 0];
            AP.Complex[,] q = new AP.Complex[0, 0];
            int i = 0;
            int k = 0;
            double v = 0;
            int i_ = 0;

            a = (AP.Complex[,])a.Clone();

            System.Diagnostics.Debug.Assert(zneeded == 0 | zneeded == 1, "HermitianEVD: incorrect ZNeeded");

            //
            // Reduce to tridiagonal form
            //
            ortfac.hmatrixtd(ref a, n, isupper, ref tau, ref d, ref e);
            if (zneeded == 1)
            {
                ortfac.hmatrixtdunpackq(ref a, n, isupper, ref tau, ref q);
                zneeded = 2;
            }

            //
            // TDEVD
            //
            result = smatrixtdevd(ref d, e, n, zneeded, ref t);

            //
            // Eigenvectors are needed
            // Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T
            //
            if (result & zneeded != 0)
            {
                work = new double[n - 1 + 1];
                z = new AP.Complex[n - 1 + 1, n - 1 + 1];
                for (i = 0; i <= n - 1; i++)
                {

                    //
                    // Calculate real part
                    //
                    for (k = 0; k <= n - 1; k++)
                    {
                        work[k] = 0;
                    }
                    for (k = 0; k <= n - 1; k++)
                    {
                        v = q[i, k].x;
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            work[i_] = work[i_] + v * t[k, i_];
                        }
                    }
                    for (k = 0; k <= n - 1; k++)
                    {
                        z[i, k].x = work[k];
                    }

                    //
                    // Calculate imaginary part
                    //
                    for (k = 0; k <= n - 1; k++)
                    {
                        work[k] = 0;
                    }
                    for (k = 0; k <= n - 1; k++)
                    {
                        v = q[i, k].y;
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            work[i_] = work[i_] + v * t[k, i_];
                        }
                    }
                    for (k = 0; k <= n - 1; k++)
                    {
                        z[i, k].y = work[k];
                    }
                }
            }
            return result;
        }
コード例 #4
0
ファイル: rcond.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Internal subroutine for condition number estimation

          -- LAPACK routine (version 3.0) --
             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
             Courant Institute, Argonne National Lab, and Rice University
             February 29, 1992
        *************************************************************************/
        private static void hpdmatrixrcondcholeskyinternal(ref AP.Complex[,] cha,
            int n,
            bool isupper,
            bool isnormprovided,
            double anorm,
            ref double rc)
        {
            int[] isave = new int[0];
            double[] rsave = new double[0];
            AP.Complex[] ex = new AP.Complex[0];
            AP.Complex[] ev = new AP.Complex[0];
            AP.Complex[] tmp = new AP.Complex[0];
            int kase = 0;
            double ainvnm = 0;
            AP.Complex v = 0;
            int i = 0;
            int j = 0;
            double sa = 0;
            double maxgrowth = 0;
            int i_ = 0;
            int i1_ = 0;

            System.Diagnostics.Debug.Assert(n >= 1);
            tmp = new AP.Complex[n];

            //
            // RC=0 if something happens
            //
            rc = 0;

            //
            // prepare parameters for triangular solver
            //
            maxgrowth = 1 / rcondthreshold();
            sa = 0;
            if (isupper)
            {
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = i; j <= n - 1; j++)
                    {
                        sa = Math.Max(sa, AP.Math.AbsComplex(cha[i, j]));
                    }
                }
            }
            else
            {
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= i; j++)
                    {
                        sa = Math.Max(sa, AP.Math.AbsComplex(cha[i, j]));
                    }
                }
            }
            if ((double)(sa) == (double)(0))
            {
                sa = 1;
            }
            sa = 1 / sa;

            //
            // Estimate the norm of A
            //
            if (!isnormprovided)
            {
                anorm = 0;
                kase = 0;
                while (true)
                {
                    cmatrixestimatenorm(n, ref ev, ref ex, ref anorm, ref kase, ref isave, ref rsave);
                    if (kase == 0)
                    {
                        break;
                    }
                    if (isupper)
                    {

                        //
                        // Multiply by U
                        //
                        for (i = 1; i <= n; i++)
                        {
                            i1_ = (i) - (i - 1);
                            v = 0.0;
                            for (i_ = i - 1; i_ <= n - 1; i_++)
                            {
                                v += cha[i - 1, i_] * ex[i_ + i1_];
                            }
                            ex[i] = v;
                        }
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = sa * ex[i_];
                        }

                        //
                        // Multiply by U'
                        //
                        for (i = 0; i <= n - 1; i++)
                        {
                            tmp[i] = 0;
                        }
                        for (i = 0; i <= n - 1; i++)
                        {
                            v = ex[i + 1];
                            for (i_ = i; i_ <= n - 1; i_++)
                            {
                                tmp[i_] = tmp[i_] + v * AP.Math.Conj(cha[i, i_]);
                            }
                        }
                        i1_ = (0) - (1);
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = tmp[i_ + i1_];
                        }
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = sa * ex[i_];
                        }
                    }
                    else
                    {

                        //
                        // Multiply by L'
                        //
                        for (i = 0; i <= n - 1; i++)
                        {
                            tmp[i] = 0;
                        }
                        for (i = 0; i <= n - 1; i++)
                        {
                            v = ex[i + 1];
                            for (i_ = 0; i_ <= i; i_++)
                            {
                                tmp[i_] = tmp[i_] + v * AP.Math.Conj(cha[i, i_]);
                            }
                        }
                        i1_ = (0) - (1);
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = tmp[i_ + i1_];
                        }
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = sa * ex[i_];
                        }

                        //
                        // Multiply by L
                        //
                        for (i = n; i >= 1; i--)
                        {
                            i1_ = (1) - (0);
                            v = 0.0;
                            for (i_ = 0; i_ <= i - 1; i_++)
                            {
                                v += cha[i - 1, i_] * ex[i_ + i1_];
                            }
                            ex[i] = v;
                        }
                        for (i_ = 1; i_ <= n; i_++)
                        {
                            ex[i_] = sa * ex[i_];
                        }
                    }
                }
            }

            //
            // Quick return if possible
            // After this block we assume that ANORM<>0
            //
            if ((double)(anorm) == (double)(0))
            {
                return;
            }
            if (n == 1)
            {
                rc = 1;
                return;
            }

            //
            // Estimate the norm of inv(A).
            //
            ainvnm = 0;
            kase = 0;
            while (true)
            {
                cmatrixestimatenorm(n, ref ev, ref ex, ref ainvnm, ref kase, ref isave, ref rsave);
                if (kase == 0)
                {
                    break;
                }
                for (i = 0; i <= n - 1; i++)
                {
                    ex[i] = ex[i + 1];
                }
                if (isupper)
                {

                    //
                    // Multiply by inv(U').
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref cha, sa, n, ref ex, isupper, 2, false, maxgrowth))
                    {
                        return;
                    }

                    //
                    // Multiply by inv(U).
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref cha, sa, n, ref ex, isupper, 0, false, maxgrowth))
                    {
                        return;
                    }
                }
                else
                {

                    //
                    // Multiply by inv(L).
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref cha, sa, n, ref ex, isupper, 0, false, maxgrowth))
                    {
                        return;
                    }

                    //
                    // Multiply by inv(L').
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref cha, sa, n, ref ex, isupper, 2, false, maxgrowth))
                    {
                        return;
                    }
                }
                for (i = n - 1; i >= 0; i--)
                {
                    ex[i + 1] = ex[i];
                }
            }

            //
            // Compute the estimate of the reciprocal condition number.
            //
            if ((double)(ainvnm) != (double)(0))
            {
                rc = 1 / ainvnm;
                rc = rc / anorm;
                if ((double)(rc) < (double)(rcondthreshold()))
                {
                    rc = 0;
                }
            }
        }
コード例 #5
0
ファイル: rcond.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Condition number estimation

          -- LAPACK routine (version 3.0) --
             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
             Courant Institute, Argonne National Lab, and Rice University
             March 31, 1993
        *************************************************************************/
        private static void cmatrixrcondluinternal(ref AP.Complex[,] lua,
            int n,
            bool onenorm,
            bool isanormprovided,
            double anorm,
            ref double rc)
        {
            AP.Complex[] ex = new AP.Complex[0];
            AP.Complex[] cwork2 = new AP.Complex[0];
            AP.Complex[] cwork3 = new AP.Complex[0];
            AP.Complex[] cwork4 = new AP.Complex[0];
            int[] isave = new int[0];
            double[] rsave = new double[0];
            int kase = 0;
            int kase1 = 0;
            double ainvnm = 0;
            AP.Complex v = 0;
            int i = 0;
            int j = 0;
            double su = 0;
            double sl = 0;
            double maxgrowth = 0;
            int i_ = 0;
            int i1_ = 0;

            if (n <= 0)
            {
                return;
            }
            cwork2 = new AP.Complex[n + 1];
            rc = 0;
            if (n == 0)
            {
                rc = 1;
                return;
            }

            //
            // prepare parameters for triangular solver
            //
            maxgrowth = 1 / rcondthreshold();
            su = 0;
            sl = 1;
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= i - 1; j++)
                {
                    sl = Math.Max(sl, AP.Math.AbsComplex(lua[i, j]));
                }
                for (j = i; j <= n - 1; j++)
                {
                    su = Math.Max(su, AP.Math.AbsComplex(lua[i, j]));
                }
            }
            if ((double)(su) == (double)(0))
            {
                su = 1;
            }
            su = 1 / su;
            sl = 1 / sl;

            //
            // Estimate the norm of SU*SL*A.
            //
            if (!isanormprovided)
            {
                anorm = 0;
                if (onenorm)
                {
                    kase1 = 1;
                }
                else
                {
                    kase1 = 2;
                }
                kase = 0;
                do
                {
                    cmatrixestimatenorm(n, ref cwork4, ref ex, ref anorm, ref kase, ref isave, ref rsave);
                    if (kase != 0)
                    {
                        if (kase == kase1)
                        {

                            //
                            // Multiply by U
                            //
                            for (i = 1; i <= n; i++)
                            {
                                i1_ = (i) - (i - 1);
                                v = 0.0;
                                for (i_ = i - 1; i_ <= n - 1; i_++)
                                {
                                    v += lua[i - 1, i_] * ex[i_ + i1_];
                                }
                                ex[i] = v;
                            }

                            //
                            // Multiply by L
                            //
                            for (i = n; i >= 1; i--)
                            {
                                v = 0;
                                if (i > 1)
                                {
                                    i1_ = (1) - (0);
                                    v = 0.0;
                                    for (i_ = 0; i_ <= i - 2; i_++)
                                    {
                                        v += lua[i - 1, i_] * ex[i_ + i1_];
                                    }
                                }
                                ex[i] = v + ex[i];
                            }
                        }
                        else
                        {

                            //
                            // Multiply by L'
                            //
                            for (i = 1; i <= n; i++)
                            {
                                cwork2[i] = 0;
                            }
                            for (i = 1; i <= n; i++)
                            {
                                v = ex[i];
                                if (i > 1)
                                {
                                    i1_ = (0) - (1);
                                    for (i_ = 1; i_ <= i - 1; i_++)
                                    {
                                        cwork2[i_] = cwork2[i_] + v * AP.Math.Conj(lua[i - 1, i_ + i1_]);
                                    }
                                }
                                cwork2[i] = cwork2[i] + v;
                            }

                            //
                            // Multiply by U'
                            //
                            for (i = 1; i <= n; i++)
                            {
                                ex[i] = 0;
                            }
                            for (i = 1; i <= n; i++)
                            {
                                v = cwork2[i];
                                i1_ = (i - 1) - (i);
                                for (i_ = i; i_ <= n; i_++)
                                {
                                    ex[i_] = ex[i_] + v * AP.Math.Conj(lua[i - 1, i_ + i1_]);
                                }
                            }
                        }
                    }
                }
                while (kase != 0);
            }

            //
            // Scale according to SU/SL
            //
            anorm = anorm * su * sl;

            //
            // Quick return if possible
            //
            if ((double)(anorm) == (double)(0))
            {
                return;
            }

            //
            // Estimate the norm of inv(A).
            //
            ainvnm = 0;
            if (onenorm)
            {
                kase1 = 1;
            }
            else
            {
                kase1 = 2;
            }
            kase = 0;
            while (true)
            {
                cmatrixestimatenorm(n, ref cwork4, ref ex, ref ainvnm, ref kase, ref isave, ref rsave);
                if (kase == 0)
                {
                    break;
                }

                //
                // From 1-based to 0-based
                //
                for (i = 0; i <= n - 1; i++)
                {
                    ex[i] = ex[i + 1];
                }

                //
                // multiply by inv(A) or inv(A')
                //
                if (kase == kase1)
                {

                    //
                    // Multiply by inv(L).
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref lua, sl, n, ref ex, false, 0, true, maxgrowth))
                    {
                        rc = 0;
                        return;
                    }

                    //
                    // Multiply by inv(U).
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref lua, su, n, ref ex, true, 0, false, maxgrowth))
                    {
                        rc = 0;
                        return;
                    }
                }
                else
                {

                    //
                    // Multiply by inv(U').
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref lua, su, n, ref ex, true, 2, false, maxgrowth))
                    {
                        rc = 0;
                        return;
                    }

                    //
                    // Multiply by inv(L').
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref lua, sl, n, ref ex, false, 2, true, maxgrowth))
                    {
                        rc = 0;
                        return;
                    }
                }

                //
                // from 0-based to 1-based
                //
                for (i = n - 1; i >= 0; i--)
                {
                    ex[i + 1] = ex[i];
                }
            }

            //
            // Compute the estimate of the reciprocal condition number.
            //
            if ((double)(ainvnm) != (double)(0))
            {
                rc = 1 / ainvnm;
                rc = rc / anorm;
                if ((double)(rc) < (double)(rcondthreshold()))
                {
                    rc = 0;
                }
            }
        }
コード例 #6
0
ファイル: trfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Cache-oblivious Cholesky decomposition

        The algorithm computes Cholesky decomposition  of  a  Hermitian  positive-
        definite matrix. The result of an algorithm is a representation  of  A  as
        A=U'*U  or A=L*L' (here X' detones conj(X^T)).

        INPUT PARAMETERS:
            A       -   upper or lower triangle of a factorized matrix.
                        array with elements [0..N-1, 0..N-1].
            N       -   size of matrix A.
            IsUpper -   if IsUpper=True, then A contains an upper triangle of
                        a symmetric matrix, otherwise A contains a lower one.

        OUTPUT PARAMETERS:
            A       -   the result of factorization. If IsUpper=True, then
                        the upper triangle contains matrix U, so that A = U'*U,
                        and the elements below the main diagonal are not modified.
                        Similarly, if IsUpper = False.

        RESULT:
            If  the  matrix  is  positive-definite,  the  function  returns  True.
            Otherwise, the function returns False. Contents of A is not determined
            in such case.

          -- ALGLIB routine --
             15.12.2009
             Bochkanov Sergey
        *************************************************************************/
        public static bool hpdmatrixcholesky(ref AP.Complex[,] a,
            int n,
            bool isupper)
        {
            bool result = new bool();
            AP.Complex[] tmp = new AP.Complex[0];

            if (n < 1)
            {
                result = false;
                return result;
            }
            tmp = new AP.Complex[2 * n];
            result = hpdmatrixcholeskyrec(ref a, 0, n, isupper, ref tmp);
            return result;
        }
コード例 #7
0
ファイル: rcond.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Condition number estimation

          -- LAPACK routine (version 3.0) --
             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
             Courant Institute, Argonne National Lab, and Rice University
             March 31, 1993
        *************************************************************************/
        private static void cmatrixrcondtrinternal(ref AP.Complex[,] a,
            int n,
            bool isupper,
            bool isunit,
            bool onenorm,
            double anorm,
            ref double rc)
        {
            AP.Complex[] ex = new AP.Complex[0];
            AP.Complex[] cwork2 = new AP.Complex[0];
            AP.Complex[] cwork3 = new AP.Complex[0];
            AP.Complex[] cwork4 = new AP.Complex[0];
            int[] isave = new int[0];
            double[] rsave = new double[0];
            int kase = 0;
            int kase1 = 0;
            double ainvnm = 0;
            AP.Complex v = 0;
            int i = 0;
            int j = 0;
            int j1 = 0;
            int j2 = 0;
            double s = 0;
            double maxgrowth = 0;


            //
            // RC=0 if something happens
            //
            rc = 0;

            //
            // init
            //
            if (n <= 0)
            {
                return;
            }
            if (n == 0)
            {
                rc = 1;
                return;
            }
            cwork2 = new AP.Complex[n + 1];

            //
            // prepare parameters for triangular solver
            //
            maxgrowth = 1 / rcondthreshold();
            s = 0;
            for (i = 0; i <= n - 1; i++)
            {
                if (isupper)
                {
                    j1 = i + 1;
                    j2 = n - 1;
                }
                else
                {
                    j1 = 0;
                    j2 = i - 1;
                }
                for (j = j1; j <= j2; j++)
                {
                    s = Math.Max(s, AP.Math.AbsComplex(a[i, j]));
                }
                if (isunit)
                {
                    s = Math.Max(s, 1);
                }
                else
                {
                    s = Math.Max(s, AP.Math.AbsComplex(a[i, i]));
                }
            }
            if ((double)(s) == (double)(0))
            {
                s = 1;
            }
            s = 1 / s;

            //
            // Scale according to S
            //
            anorm = anorm * s;

            //
            // Quick return if possible
            //
            if ((double)(anorm) == (double)(0))
            {
                return;
            }

            //
            // Estimate the norm of inv(A).
            //
            ainvnm = 0;
            if (onenorm)
            {
                kase1 = 1;
            }
            else
            {
                kase1 = 2;
            }
            kase = 0;
            while (true)
            {
                cmatrixestimatenorm(n, ref cwork4, ref ex, ref ainvnm, ref kase, ref isave, ref rsave);
                if (kase == 0)
                {
                    break;
                }

                //
                // From 1-based to 0-based
                //
                for (i = 0; i <= n - 1; i++)
                {
                    ex[i] = ex[i + 1];
                }

                //
                // multiply by inv(A) or inv(A')
                //
                if (kase == kase1)
                {

                    //
                    // multiply by inv(A)
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref a, s, n, ref ex, isupper, 0, isunit, maxgrowth))
                    {
                        return;
                    }
                }
                else
                {

                    //
                    // multiply by inv(A')
                    //
                    if (!safesolve.cmatrixscaledtrsafesolve(ref a, s, n, ref ex, isupper, 2, isunit, maxgrowth))
                    {
                        return;
                    }
                }

                //
                // from 0-based to 1-based
                //
                for (i = n - 1; i >= 0; i--)
                {
                    ex[i + 1] = ex[i];
                }
            }

            //
            // Compute the estimate of the reciprocal condition number.
            //
            if ((double)(ainvnm) != (double)(0))
            {
                rc = 1 / ainvnm;
                rc = rc / anorm;
                if ((double)(rc) < (double)(rcondthreshold()))
                {
                    rc = 0;
                }
            }
        }
コード例 #8
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Reduction of a Hermitian matrix which is given  by  its  higher  or  lower
        triangular part to a real  tridiagonal  matrix  using  unitary  similarity
        transformation: Q'*A*Q = T.

        Input parameters:
            A       -   matrix to be transformed
                        array with elements [0..N-1, 0..N-1].
            N       -   size of matrix A.
            IsUpper -   storage format. If IsUpper = True, then matrix A is  given
                        by its upper triangle, and the lower triangle is not  used
                        and not modified by the algorithm, and vice versa
                        if IsUpper = False.

        Output parameters:
            A       -   matrices T and Q in  compact form (see lower)
            Tau     -   array of factors which are forming matrices H(i)
                        array with elements [0..N-2].
            D       -   main diagonal of real symmetric matrix T.
                        array with elements [0..N-1].
            E       -   secondary diagonal of real symmetric matrix T.
                        array with elements [0..N-2].


          If IsUpper=True, the matrix Q is represented as a product of elementary
          reflectors

             Q = H(n-2) . . . H(2) H(0).

          Each H(i) has the form

             H(i) = I - tau * v * v'

          where tau is a complex scalar, and v is a complex vector with
          v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
          A(0:i-1,i+1), and tau in TAU(i).

          If IsUpper=False, the matrix Q is represented as a product of elementary
          reflectors

             Q = H(0) H(2) . . . H(n-2).

          Each H(i) has the form

             H(i) = I - tau * v * v'

          where tau is a complex scalar, and v is a complex vector with
          v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
          and tau in TAU(i).

          The contents of A on exit are illustrated by the following examples
          with n = 5:

          if UPLO = 'U':                       if UPLO = 'L':

            (  d   e   v1  v2  v3 )              (  d                  )
            (      d   e   v2  v3 )              (  e   d              )
            (          d   e   v3 )              (  v0  e   d          )
            (              d   e  )              (  v0  v1  e   d      )
            (                  d  )              (  v0  v1  v2  e   d  )

        where d and e denote diagonal and off-diagonal elements of T, and vi
        denotes an element of the vector defining H(i).

          -- LAPACK routine (version 3.0) --
             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
             Courant Institute, Argonne National Lab, and Rice University
             October 31, 1992
        *************************************************************************/
        public static void hmatrixtd(ref AP.Complex[,] a,
            int n,
            bool isupper,
            ref AP.Complex[] tau,
            ref double[] d,
            ref double[] e)
        {
            int i = 0;
            AP.Complex alpha = 0;
            AP.Complex taui = 0;
            AP.Complex v = 0;
            AP.Complex[] t = new AP.Complex[0];
            AP.Complex[] t2 = new AP.Complex[0];
            AP.Complex[] t3 = new AP.Complex[0];
            int i_ = 0;
            int i1_ = 0;

            if (n <= 0)
            {
                return;
            }
            for (i = 0; i <= n - 1; i++)
            {
                System.Diagnostics.Debug.Assert((double)(a[i, i].y) == (double)(0));
            }
            if (n > 1)
            {
                tau = new AP.Complex[n - 2 + 1];
                e = new double[n - 2 + 1];
            }
            d = new double[n - 1 + 1];
            t = new AP.Complex[n - 1 + 1];
            t2 = new AP.Complex[n - 1 + 1];
            t3 = new AP.Complex[n - 1 + 1];
            if (isupper)
            {

                //
                // Reduce the upper triangle of A
                //
                a[n - 1, n - 1] = a[n - 1, n - 1].x;
                for (i = n - 2; i >= 0; i--)
                {

                    //
                    // Generate elementary reflector H = I+1 - tau * v * v'
                    //
                    alpha = a[i, i + 1];
                    t[1] = alpha;
                    if (i >= 1)
                    {
                        i1_ = (0) - (2);
                        for (i_ = 2; i_ <= i + 1; i_++)
                        {
                            t[i_] = a[i_ + i1_, i + 1];
                        }
                    }
                    creflections.complexgeneratereflection(ref t, i + 1, ref taui);
                    if (i >= 1)
                    {
                        i1_ = (2) - (0);
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            a[i_, i + 1] = t[i_ + i1_];
                        }
                    }
                    alpha = t[1];
                    e[i] = alpha.x;
                    if (taui != 0)
                    {

                        //
                        // Apply H(I+1) from both sides to A
                        //
                        a[i, i + 1] = 1;

                        //
                        // Compute  x := tau * A * v  storing x in TAU
                        //
                        i1_ = (0) - (1);
                        for (i_ = 1; i_ <= i + 1; i_++)
                        {
                            t[i_] = a[i_ + i1_, i + 1];
                        }
                        hblas.hermitianmatrixvectormultiply(ref a, isupper, 0, i, ref t, taui, ref t2);
                        i1_ = (1) - (0);
                        for (i_ = 0; i_ <= i; i_++)
                        {
                            tau[i_] = t2[i_ + i1_];
                        }

                        //
                        // Compute  w := x - 1/2 * tau * (x'*v) * v
                        //
                        v = 0.0;
                        for (i_ = 0; i_ <= i; i_++)
                        {
                            v += AP.Math.Conj(tau[i_]) * a[i_, i + 1];
                        }
                        alpha = -(0.5 * taui * v);
                        for (i_ = 0; i_ <= i; i_++)
                        {
                            tau[i_] = tau[i_] + alpha * a[i_, i + 1];
                        }

                        //
                        // Apply the transformation as a rank-2 update:
                        //    A := A - v * w' - w * v'
                        //
                        i1_ = (0) - (1);
                        for (i_ = 1; i_ <= i + 1; i_++)
                        {
                            t[i_] = a[i_ + i1_, i + 1];
                        }
                        i1_ = (0) - (1);
                        for (i_ = 1; i_ <= i + 1; i_++)
                        {
                            t3[i_] = tau[i_ + i1_];
                        }
                        hblas.hermitianrank2update(ref a, isupper, 0, i, ref t, ref t3, ref t2, -1);
                    }
                    else
                    {
                        a[i, i] = a[i, i].x;
                    }
                    a[i, i + 1] = e[i];
                    d[i + 1] = a[i + 1, i + 1].x;
                    tau[i] = taui;
                }
                d[0] = a[0, 0].x;
            }
            else
            {

                //
                // Reduce the lower triangle of A
                //
                a[0, 0] = a[0, 0].x;
                for (i = 0; i <= n - 2; i++)
                {

                    //
                    // Generate elementary reflector H = I - tau * v * v'
                    //
                    i1_ = (i + 1) - (1);
                    for (i_ = 1; i_ <= n - i - 1; i_++)
                    {
                        t[i_] = a[i_ + i1_, i];
                    }
                    creflections.complexgeneratereflection(ref t, n - i - 1, ref taui);
                    i1_ = (1) - (i + 1);
                    for (i_ = i + 1; i_ <= n - 1; i_++)
                    {
                        a[i_, i] = t[i_ + i1_];
                    }
                    e[i] = a[i + 1, i].x;
                    if (taui != 0)
                    {

                        //
                        // Apply H(i) from both sides to A(i+1:n,i+1:n)
                        //
                        a[i + 1, i] = 1;

                        //
                        // Compute  x := tau * A * v  storing y in TAU
                        //
                        i1_ = (i + 1) - (1);
                        for (i_ = 1; i_ <= n - i - 1; i_++)
                        {
                            t[i_] = a[i_ + i1_, i];
                        }
                        hblas.hermitianmatrixvectormultiply(ref a, isupper, i + 1, n - 1, ref t, taui, ref t2);
                        i1_ = (1) - (i);
                        for (i_ = i; i_ <= n - 2; i_++)
                        {
                            tau[i_] = t2[i_ + i1_];
                        }

                        //
                        // Compute  w := x - 1/2 * tau * (x'*v) * v
                        //
                        i1_ = (i + 1) - (i);
                        v = 0.0;
                        for (i_ = i; i_ <= n - 2; i_++)
                        {
                            v += AP.Math.Conj(tau[i_]) * a[i_ + i1_, i];
                        }
                        alpha = -(0.5 * taui * v);
                        i1_ = (i + 1) - (i);
                        for (i_ = i; i_ <= n - 2; i_++)
                        {
                            tau[i_] = tau[i_] + alpha * a[i_ + i1_, i];
                        }

                        //
                        // Apply the transformation as a rank-2 update:
                        // A := A - v * w' - w * v'
                        //
                        i1_ = (i + 1) - (1);
                        for (i_ = 1; i_ <= n - i - 1; i_++)
                        {
                            t[i_] = a[i_ + i1_, i];
                        }
                        i1_ = (i) - (1);
                        for (i_ = 1; i_ <= n - i - 1; i_++)
                        {
                            t2[i_] = tau[i_ + i1_];
                        }
                        hblas.hermitianrank2update(ref a, isupper, i + 1, n - 1, ref t, ref t2, ref t3, -1);
                    }
                    else
                    {
                        a[i + 1, i + 1] = a[i + 1, i + 1].x;
                    }
                    a[i + 1, i] = e[i];
                    d[i] = a[i, i].x;
                    tau[i] = taui;
                }
                d[n - 1] = a[n - 1, n - 1].x;
            }
        }
コード例 #9
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Unpacking matrix Q which reduces a Hermitian matrix to a real  tridiagonal
        form.

        Input parameters:
            A       -   the result of a HMatrixTD subroutine
            N       -   size of matrix A.
            IsUpper -   storage format (a parameter of HMatrixTD subroutine)
            Tau     -   the result of a HMatrixTD subroutine

        Output parameters:
            Q       -   transformation matrix.
                        array with elements [0..N-1, 0..N-1].

          -- ALGLIB --
             Copyright 2005-2010 by Bochkanov Sergey
        *************************************************************************/
        public static void hmatrixtdunpackq(ref AP.Complex[,] a,
            int n,
            bool isupper,
            ref AP.Complex[] tau,
            ref AP.Complex[,] q)
        {
            int i = 0;
            int j = 0;
            AP.Complex[] v = new AP.Complex[0];
            AP.Complex[] work = new AP.Complex[0];
            int i_ = 0;
            int i1_ = 0;

            if (n == 0)
            {
                return;
            }

            //
            // init
            //
            q = new AP.Complex[n - 1 + 1, n - 1 + 1];
            v = new AP.Complex[n + 1];
            work = new AP.Complex[n - 1 + 1];
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    if (i == j)
                    {
                        q[i, j] = 1;
                    }
                    else
                    {
                        q[i, j] = 0;
                    }
                }
            }

            //
            // unpack Q
            //
            if (isupper)
            {
                for (i = 0; i <= n - 2; i++)
                {

                    //
                    // Apply H(i)
                    //
                    i1_ = (0) - (1);
                    for (i_ = 1; i_ <= i + 1; i_++)
                    {
                        v[i_] = a[i_ + i1_, i + 1];
                    }
                    v[i + 1] = 1;
                    creflections.complexapplyreflectionfromtheleft(ref q, tau[i], ref v, 0, i, 0, n - 1, ref work);
                }
            }
            else
            {
                for (i = n - 2; i >= 0; i--)
                {

                    //
                    // Apply H(i)
                    //
                    i1_ = (i + 1) - (1);
                    for (i_ = 1; i_ <= n - i - 1; i_++)
                    {
                        v[i_] = a[i_ + i1_, i];
                    }
                    v[1] = 1;
                    creflections.complexapplyreflectionfromtheleft(ref q, tau[i], ref v, i + 1, n - 1, 0, n - 1, ref work);
                }
            }
        }
コード例 #10
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Partial unpacking of matrix Q from LQ decomposition of a complex matrix A.

        Input parameters:
            A           -   matrices Q and R in compact form.
                            Output of CMatrixLQ subroutine .
            M           -   number of rows in matrix A. M>=0.
            N           -   number of columns in matrix A. N>=0.
            Tau         -   scalar factors which are used to form Q.
                            Output of CMatrixLQ subroutine .
            QRows       -   required number of rows in matrix Q. N>=QColumns>=0.

        Output parameters:
            Q           -   first QRows rows of matrix Q.
                            Array whose index ranges within [0..QRows-1, 0..N-1].
                            If QRows=0, array isn't changed.

          -- ALGLIB routine --
             17.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixlqunpackq(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[] tau,
            int qrows,
            ref AP.Complex[,] q)
        {
            AP.Complex[] work = new AP.Complex[0];
            AP.Complex[] t = new AP.Complex[0];
            AP.Complex[] taubuf = new AP.Complex[0];
            int minmn = 0;
            int refcnt = 0;
            AP.Complex[,] tmpa = new AP.Complex[0, 0];
            AP.Complex[,] tmpt = new AP.Complex[0, 0];
            AP.Complex[,] tmpr = new AP.Complex[0, 0];
            int blockstart = 0;
            int blocksize = 0;
            int columnscount = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            AP.Complex v = 0;
            int i_ = 0;
            int i1_ = 0;

            if (m <= 0 | n <= 0)
            {
                return;
            }

            //
            // Init
            //
            minmn = Math.Min(m, n);
            refcnt = Math.Min(minmn, qrows);
            work = new AP.Complex[Math.Max(m, n) + 1];
            t = new AP.Complex[Math.Max(m, n) + 1];
            taubuf = new AP.Complex[minmn];
            tmpa = new AP.Complex[ablas.ablascomplexblocksize(ref a), n];
            tmpt = new AP.Complex[ablas.ablascomplexblocksize(ref a), ablas.ablascomplexblocksize(ref a)];
            tmpr = new AP.Complex[qrows, 2 * ablas.ablascomplexblocksize(ref a)];
            q = new AP.Complex[qrows, n];
            for (i = 0; i <= qrows - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    if (i == j)
                    {
                        q[i, j] = 1;
                    }
                    else
                    {
                        q[i, j] = 0;
                    }
                }
            }

            //
            // Blocked code
            //
            blockstart = ablas.ablascomplexblocksize(ref a) * (refcnt / ablas.ablascomplexblocksize(ref a));
            blocksize = refcnt - blockstart;
            while (blockstart >= 0)
            {
                columnscount = n - blockstart;

                //
                // LQ decomposition of submatrix.
                // Matrix is copied to temporary storage to solve
                // some TLB issues arising from non-contiguous memory
                // access pattern.
                //
                ablas.cmatrixcopy(blocksize, columnscount, ref a, blockstart, blockstart, ref tmpa, 0, 0);
                i1_ = (blockstart) - (0);
                for (i_ = 0; i_ <= blocksize - 1; i_++)
                {
                    taubuf[i_] = tau[i_ + i1_];
                }

                //
                // Update matrix, choose between:
                // a) Level 2 algorithm (when the rest of the matrix is small enough)
                // b) blocked algorithm, see algorithm 5 from  'A storage efficient WY
                //    representation for products of Householder transformations',
                //    by R. Schreiber and C. Van Loan.
                //
                if (qrows >= 2 * ablas.ablascomplexblocksize(ref a))
                {

                    //
                    // Prepare block reflector
                    //
                    cmatrixblockreflector(ref tmpa, ref taubuf, false, columnscount, blocksize, ref tmpt, ref work);

                    //
                    // Multiply the rest of A by Q'.
                    //
                    // Q'  = E + Y*T'*Y'  = E + TmpA'*TmpT'*TmpA
                    //
                    ablas.cmatrixgemm(qrows, blocksize, columnscount, 1.0, ref q, 0, blockstart, 0, ref tmpa, 0, 0, 2, 0.0, ref tmpr, 0, 0);
                    ablas.cmatrixgemm(qrows, blocksize, blocksize, 1.0, ref tmpr, 0, 0, 0, ref tmpt, 0, 0, 2, 0.0, ref tmpr, 0, blocksize);
                    ablas.cmatrixgemm(qrows, columnscount, blocksize, 1.0, ref tmpr, 0, blocksize, 0, ref tmpa, 0, 0, 0, 1.0, ref q, 0, blockstart);
                }
                else
                {

                    //
                    // Level 2 algorithm
                    //
                    for (i = blocksize - 1; i >= 0; i--)
                    {
                        i1_ = (i) - (1);
                        for (i_ = 1; i_ <= columnscount - i; i_++)
                        {
                            t[i_] = AP.Math.Conj(tmpa[i, i_ + i1_]);
                        }
                        t[1] = 1;
                        creflections.complexapplyreflectionfromtheright(ref q, AP.Math.Conj(taubuf[i]), ref t, 0, qrows - 1, blockstart + i, n - 1, ref work);
                    }
                }

                //
                // Advance
                //
                blockstart = blockstart - ablas.ablascomplexblocksize(ref a);
                blocksize = ablas.ablascomplexblocksize(ref a);
            }
        }
コード例 #11
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Unpacking of matrix L from the LQ decomposition of a matrix A

        Input parameters:
            A       -   matrices Q and L in compact form.
                        Output of CMatrixLQ subroutine.
            M       -   number of rows in given matrix A. M>=0.
            N       -   number of columns in given matrix A. N>=0.

        Output parameters:
            L       -   matrix L, array[0..M-1, 0..N-1].

          -- ALGLIB routine --
             17.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixlqunpackl(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[,] l)
        {
            int i = 0;
            int k = 0;
            int i_ = 0;

            if (m <= 0 | n <= 0)
            {
                return;
            }
            l = new AP.Complex[m, n];
            for (i = 0; i <= n - 1; i++)
            {
                l[0, i] = 0;
            }
            for (i = 1; i <= m - 1; i++)
            {
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    l[i, i_] = l[0, i_];
                }
            }
            for (i = 0; i <= m - 1; i++)
            {
                k = Math.Min(i, n - 1);
                for (i_ = 0; i_ <= k; i_++)
                {
                    l[i, i_] = a[i, i_];
                }
            }
        }
コード例 #12
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Unpacking of matrix R from the QR decomposition of a matrix A

        Input parameters:
            A       -   matrices Q and R in compact form.
                        Output of CMatrixQR subroutine.
            M       -   number of rows in given matrix A. M>=0.
            N       -   number of columns in given matrix A. N>=0.

        Output parameters:
            R       -   matrix R, array[0..M-1, 0..N-1].

          -- ALGLIB routine --
             17.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixqrunpackr(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[,] r)
        {
            int i = 0;
            int k = 0;
            int i_ = 0;

            if (m <= 0 | n <= 0)
            {
                return;
            }
            k = Math.Min(m, n);
            r = new AP.Complex[m, n];
            for (i = 0; i <= n - 1; i++)
            {
                r[0, i] = 0;
            }
            for (i = 1; i <= m - 1; i++)
            {
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    r[i, i_] = r[0, i_];
                }
            }
            for (i = 0; i <= k - 1; i++)
            {
                for (i_ = i; i_ <= n - 1; i_++)
                {
                    r[i, i_] = a[i, i_];
                }
            }
        }
コード例 #13
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Partial unpacking of matrix Q from QR decomposition of a complex matrix A.

        Input parameters:
            A           -   matrices Q and R in compact form.
                            Output of CMatrixQR subroutine .
            M           -   number of rows in matrix A. M>=0.
            N           -   number of columns in matrix A. N>=0.
            Tau         -   scalar factors which are used to form Q.
                            Output of CMatrixQR subroutine .
            QColumns    -   required number of columns in matrix Q. M>=QColumns>=0.

        Output parameters:
            Q           -   first QColumns columns of matrix Q.
                            Array whose index ranges within [0..M-1, 0..QColumns-1].
                            If QColumns=0, array isn't changed.

          -- ALGLIB routine --
             17.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixqrunpackq(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[] tau,
            int qcolumns,
            ref AP.Complex[,] q)
        {
            AP.Complex[] work = new AP.Complex[0];
            AP.Complex[] t = new AP.Complex[0];
            AP.Complex[] taubuf = new AP.Complex[0];
            int minmn = 0;
            int refcnt = 0;
            AP.Complex[,] tmpa = new AP.Complex[0, 0];
            AP.Complex[,] tmpt = new AP.Complex[0, 0];
            AP.Complex[,] tmpr = new AP.Complex[0, 0];
            int blockstart = 0;
            int blocksize = 0;
            int rowscount = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            AP.Complex v = 0;
            int i_ = 0;
            int i1_ = 0;

            System.Diagnostics.Debug.Assert(qcolumns <= m, "UnpackQFromQR: QColumns>M!");
            if (m <= 0 | n <= 0)
            {
                return;
            }

            //
            // init
            //
            minmn = Math.Min(m, n);
            refcnt = Math.Min(minmn, qcolumns);
            work = new AP.Complex[Math.Max(m, n) + 1];
            t = new AP.Complex[Math.Max(m, n) + 1];
            taubuf = new AP.Complex[minmn];
            tmpa = new AP.Complex[m, ablas.ablascomplexblocksize(ref a)];
            tmpt = new AP.Complex[ablas.ablascomplexblocksize(ref a), ablas.ablascomplexblocksize(ref a)];
            tmpr = new AP.Complex[2 * ablas.ablascomplexblocksize(ref a), qcolumns];
            q = new AP.Complex[m, qcolumns];
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= qcolumns - 1; j++)
                {
                    if (i == j)
                    {
                        q[i, j] = 1;
                    }
                    else
                    {
                        q[i, j] = 0;
                    }
                }
            }

            //
            // Blocked code
            //
            blockstart = ablas.ablascomplexblocksize(ref a) * (refcnt / ablas.ablascomplexblocksize(ref a));
            blocksize = refcnt - blockstart;
            while (blockstart >= 0)
            {
                rowscount = m - blockstart;

                //
                // QR decomposition of submatrix.
                // Matrix is copied to temporary storage to solve
                // some TLB issues arising from non-contiguous memory
                // access pattern.
                //
                ablas.cmatrixcopy(rowscount, blocksize, ref a, blockstart, blockstart, ref tmpa, 0, 0);
                i1_ = (blockstart) - (0);
                for (i_ = 0; i_ <= blocksize - 1; i_++)
                {
                    taubuf[i_] = tau[i_ + i1_];
                }

                //
                // Update matrix, choose between:
                // a) Level 2 algorithm (when the rest of the matrix is small enough)
                // b) blocked algorithm, see algorithm 5 from  'A storage efficient WY
                //    representation for products of Householder transformations',
                //    by R. Schreiber and C. Van Loan.
                //
                if (qcolumns >= 2 * ablas.ablascomplexblocksize(ref a))
                {

                    //
                    // Prepare block reflector
                    //
                    cmatrixblockreflector(ref tmpa, ref taubuf, true, rowscount, blocksize, ref tmpt, ref work);

                    //
                    // Multiply the rest of A by Q.
                    //
                    // Q  = E + Y*T*Y'  = E + TmpA*TmpT*TmpA'
                    //
                    ablas.cmatrixgemm(blocksize, qcolumns, rowscount, 1.0, ref tmpa, 0, 0, 2, ref q, blockstart, 0, 0, 0.0, ref tmpr, 0, 0);
                    ablas.cmatrixgemm(blocksize, qcolumns, blocksize, 1.0, ref tmpt, 0, 0, 0, ref tmpr, 0, 0, 0, 0.0, ref tmpr, blocksize, 0);
                    ablas.cmatrixgemm(rowscount, qcolumns, blocksize, 1.0, ref tmpa, 0, 0, 0, ref tmpr, blocksize, 0, 0, 1.0, ref q, blockstart, 0);
                }
                else
                {

                    //
                    // Level 2 algorithm
                    //
                    for (i = blocksize - 1; i >= 0; i--)
                    {
                        i1_ = (i) - (1);
                        for (i_ = 1; i_ <= rowscount - i; i_++)
                        {
                            t[i_] = tmpa[i_ + i1_, i];
                        }
                        t[1] = 1;
                        creflections.complexapplyreflectionfromtheleft(ref q, taubuf[i], ref t, blockstart + i, m - 1, 0, qcolumns - 1, ref work);
                    }
                }

                //
                // Advance
                //
                blockstart = blockstart - ablas.ablascomplexblocksize(ref a);
                blocksize = ablas.ablascomplexblocksize(ref a);
            }
        }
コード例 #14
0
ファイル: trfac.cs プロジェクト: mortenbakkedal/SharpMath
        public static void cmatrixplu(ref AP.Complex[,] a,
            int m,
            int n,
            ref int[] pivots)
        {
            AP.Complex[] tmp = new AP.Complex[0];
            int i = 0;
            int j = 0;
            double mx = 0;
            AP.Complex v = 0;
            int i_ = 0;


            //
            // Internal LU decomposition subroutine.
            // Never call it directly.
            //
            System.Diagnostics.Debug.Assert(m > 0, "CMatrixPLU: incorrect M!");
            System.Diagnostics.Debug.Assert(n > 0, "CMatrixPLU: incorrect N!");
            tmp = new AP.Complex[2 * Math.Max(m, n)];
            pivots = new int[Math.Min(m, n)];

            //
            // Scale matrix to avoid overflows,
            // decompose it, then scale back.
            //
            mx = 0;
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    mx = Math.Max(mx, AP.Math.AbsComplex(a[i, j]));
                }
            }
            if ((double)(mx) != (double)(0))
            {
                v = 1 / mx;
                for (i = 0; i <= m - 1; i++)
                {
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        a[i, i_] = v * a[i, i_];
                    }
                }
            }
            cmatrixplurec(ref a, 0, m, n, ref pivots, ref tmp);
            if ((double)(mx) != (double)(0))
            {
                v = mx;
                for (i = 0; i <= Math.Min(m, n) - 1; i++)
                {
                    for (i_ = i; i_ <= n - 1; i_++)
                    {
                        a[i, i_] = v * a[i, i_];
                    }
                }
            }
        }
コード例 #15
0
ファイル: matinv.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Inversion of a Hermitian positive definite matrix which is given
        by Cholesky decomposition.

        Input parameters:
            A       -   Cholesky decomposition of the matrix to be inverted:
                        A=U�*U or A = L*L'.
                        Output of  HPDMatrixCholesky subroutine.
            N       -   size of matrix A.
            IsUpper �   storage format.
                        If IsUpper = True, then matrix A is given as A = U'*U
                        (matrix contains upper triangle).
                        Similarly, if IsUpper = False, then A = L*L'.

        Output parameters:
            Info    -   return code, same as in RMatrixLUInverse
            Rep     -   solver report, same as in RMatrixLUInverse
            A       -   inverse of matrix A, same as in RMatrixLUInverse

          -- ALGLIB routine --
             10.02.2010
             Bochkanov Sergey
        *************************************************************************/
        public static void hpdmatrixcholeskyinverse(ref AP.Complex[,] a,
            int n,
            bool isupper,
            ref int info,
            ref matinvreport rep)
        {
            int i = 0;
            int j = 0;
            int info2 = 0;
            matinvreport rep2 = new matinvreport();
            AP.Complex[] tmp = new AP.Complex[0];
            AP.Complex v = 0;

            if (n < 1)
            {
                info = -1;
                return;
            }
            info = 1;

            //
            // calculate condition numbers
            //
            rep.r1 = rcond.hpdmatrixcholeskyrcond(ref a, n, isupper);
            rep.rinf = rep.r1;
            if ((double)(rep.r1) < (double)(rcond.rcondthreshold()) | (double)(rep.rinf) < (double)(rcond.rcondthreshold()))
            {
                if (isupper)
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = i; j <= n - 1; j++)
                        {
                            a[i, j] = 0;
                        }
                    }
                }
                else
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = 0; j <= i; j++)
                        {
                            a[i, j] = 0;
                        }
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }

            //
            // Inverse
            //
            tmp = new AP.Complex[n];
            hpdmatrixcholeskyinverserec(ref a, 0, n, isupper, ref tmp);
        }
コード例 #16
0
ファイル: ortfac.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        LQ decomposition of a rectangular complex matrix of size MxN

        Input parameters:
            A   -   matrix A whose indexes range within [0..M-1, 0..N-1]
            M   -   number of rows in matrix A.
            N   -   number of columns in matrix A.

        Output parameters:
            A   -   matrices Q and L in compact form
            Tau -   array of scalar factors which are used to form matrix Q. Array
                    whose indexes range within [0.. Min(M,N)-1]

        Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
        MxM, L - lower triangular (or lower trapezoid) matrix of size MxN.

          -- LAPACK routine (version 3.0) --
             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
             Courant Institute, Argonne National Lab, and Rice University
             September 30, 1994
        *************************************************************************/
        public static void cmatrixlq(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[] tau)
        {
            AP.Complex[] work = new AP.Complex[0];
            AP.Complex[] t = new AP.Complex[0];
            AP.Complex[] taubuf = new AP.Complex[0];
            int minmn = 0;
            AP.Complex[,] tmpa = new AP.Complex[0, 0];
            AP.Complex[,] tmpt = new AP.Complex[0, 0];
            AP.Complex[,] tmpr = new AP.Complex[0, 0];
            int blockstart = 0;
            int blocksize = 0;
            int columnscount = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            AP.Complex v = 0;
            int i_ = 0;
            int i1_ = 0;

            if (m <= 0 | n <= 0)
            {
                return;
            }
            minmn = Math.Min(m, n);
            work = new AP.Complex[Math.Max(m, n) + 1];
            t = new AP.Complex[Math.Max(m, n) + 1];
            tau = new AP.Complex[minmn];
            taubuf = new AP.Complex[minmn];
            tmpa = new AP.Complex[ablas.ablascomplexblocksize(ref a), n];
            tmpt = new AP.Complex[ablas.ablascomplexblocksize(ref a), ablas.ablascomplexblocksize(ref a)];
            tmpr = new AP.Complex[m, 2 * ablas.ablascomplexblocksize(ref a)];

            //
            // Blocked code
            //
            blockstart = 0;
            while (blockstart != minmn)
            {

                //
                // Determine block size
                //
                blocksize = minmn - blockstart;
                if (blocksize > ablas.ablascomplexblocksize(ref a))
                {
                    blocksize = ablas.ablascomplexblocksize(ref a);
                }
                columnscount = n - blockstart;

                //
                // LQ decomposition of submatrix.
                // Matrix is copied to temporary storage to solve
                // some TLB issues arising from non-contiguous memory
                // access pattern.
                //
                ablas.cmatrixcopy(blocksize, columnscount, ref a, blockstart, blockstart, ref tmpa, 0, 0);
                cmatrixlqbasecase(ref tmpa, blocksize, columnscount, ref work, ref t, ref taubuf);
                ablas.cmatrixcopy(blocksize, columnscount, ref tmpa, 0, 0, ref a, blockstart, blockstart);
                i1_ = (0) - (blockstart);
                for (i_ = blockstart; i_ <= blockstart + blocksize - 1; i_++)
                {
                    tau[i_] = taubuf[i_ + i1_];
                }

                //
                // Update the rest, choose between:
                // a) Level 2 algorithm (when the rest of the matrix is small enough)
                // b) blocked algorithm, see algorithm 5 from  'A storage efficient WY
                //    representation for products of Householder transformations',
                //    by R. Schreiber and C. Van Loan.
                //
                if (blockstart + blocksize <= m - 1)
                {
                    if (m - blockstart - blocksize >= 2 * ablas.ablascomplexblocksize(ref a))
                    {

                        //
                        // Prepare block reflector
                        //
                        cmatrixblockreflector(ref tmpa, ref taubuf, false, columnscount, blocksize, ref tmpt, ref work);

                        //
                        // Multiply the rest of A by Q.
                        //
                        // Q  = E + Y*T*Y'  = E + TmpA'*TmpT*TmpA
                        //
                        ablas.cmatrixgemm(m - blockstart - blocksize, blocksize, columnscount, 1.0, ref a, blockstart + blocksize, blockstart, 0, ref tmpa, 0, 0, 2, 0.0, ref tmpr, 0, 0);
                        ablas.cmatrixgemm(m - blockstart - blocksize, blocksize, blocksize, 1.0, ref tmpr, 0, 0, 0, ref tmpt, 0, 0, 0, 0.0, ref tmpr, 0, blocksize);
                        ablas.cmatrixgemm(m - blockstart - blocksize, columnscount, blocksize, 1.0, ref tmpr, 0, blocksize, 0, ref tmpa, 0, 0, 0, 1.0, ref a, blockstart + blocksize, blockstart);
                    }
                    else
                    {

                        //
                        // Level 2 algorithm
                        //
                        for (i = 0; i <= blocksize - 1; i++)
                        {
                            i1_ = (i) - (1);
                            for (i_ = 1; i_ <= columnscount - i; i_++)
                            {
                                t[i_] = AP.Math.Conj(tmpa[i, i_ + i1_]);
                            }
                            t[1] = 1;
                            creflections.complexapplyreflectionfromtheright(ref a, taubuf[i], ref t, blockstart + blocksize, m - 1, blockstart + i, n - 1, ref work);
                        }
                    }
                }

                //
                // Advance
                //
                blockstart = blockstart + blocksize;
            }
        }
コード例 #17
0
ファイル: matinv.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Triangular matrix inverse (complex)

        The subroutine inverts the following types of matrices:
            * upper triangular
            * upper triangular with unit diagonal
            * lower triangular
            * lower triangular with unit diagonal

        In case of an upper (lower) triangular matrix,  the  inverse  matrix  will
        also be upper (lower) triangular, and after the end of the algorithm,  the
        inverse matrix replaces the source matrix. The elements  below (above) the
        main diagonal are not changed by the algorithm.

        If  the matrix  has a unit diagonal, the inverse matrix also  has  a  unit
        diagonal, and the diagonal elements are not passed to the algorithm.

        Input parameters:
            A       -   matrix, array[0..N-1, 0..N-1].
            N       -   size of A.
            IsUpper -   True, if the matrix is upper triangular.
            IsUnit  -   True, if the matrix has a unit diagonal.

        Output parameters:
            Info    -   same as for RMatrixLUInverse
            Rep     -   same as for RMatrixLUInverse
            A       -   same as for RMatrixLUInverse.

          -- ALGLIB --
             Copyright 05.02.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixtrinverse(ref AP.Complex[,] a,
            int n,
            bool isupper,
            bool isunit,
            ref int info,
            ref matinvreport rep)
        {
            int i = 0;
            int j = 0;
            AP.Complex[] tmp = new AP.Complex[0];

            if (n < 1)
            {
                info = -1;
                return;
            }
            info = 1;

            //
            // calculate condition numbers
            //
            rep.r1 = rcond.cmatrixtrrcond1(ref a, n, isupper, isunit);
            rep.rinf = rcond.cmatrixtrrcondinf(ref a, n, isupper, isunit);
            if ((double)(rep.r1) < (double)(rcond.rcondthreshold()) | (double)(rep.rinf) < (double)(rcond.rcondthreshold()))
            {
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        a[i, j] = 0;
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }

            //
            // Invert
            //
            tmp = new AP.Complex[n];
            cmatrixtrinverserec(ref a, 0, n, isupper, isunit, ref tmp, ref info, ref rep);
        }
コード例 #18
0
ファイル: safesolve.cs プロジェクト: mortenbakkedal/SharpMath
        /*************************************************************************
        Internal subroutine for safe solution of

            SA*op(A)=b

        where  A  is  NxN  upper/lower  triangular/unitriangular  matrix, op(A) is
        either identity transform, transposition or Hermitian transposition, SA is
        a scaling factor such that max(|SA*A[i,j]|) is close to 1.0 in magnutude.

        This subroutine  limits  relative  growth  of  solution  (in inf-norm)  by
        MaxGrowth,  returning  False  if  growth  exceeds MaxGrowth. Degenerate or
        near-degenerate matrices are handled correctly (False is returned) as long
        as MaxGrowth is significantly less than MaxRealNumber/norm(b).

          -- ALGLIB routine --
             21.01.2010
             Bochkanov Sergey
        *************************************************************************/
        public static bool cmatrixscaledtrsafesolve(ref AP.Complex[,] a,
            double sa,
            int n,
            ref AP.Complex[] x,
            bool isupper,
            int trans,
            bool isunit,
            double maxgrowth)
        {
            bool result = new bool();
            double lnmax = 0;
            double nrmb = 0;
            double nrmx = 0;
            int i = 0;
            AP.Complex alpha = 0;
            AP.Complex beta = 0;
            AP.Complex vc = 0;
            AP.Complex[] tmp = new AP.Complex[0];
            int i_ = 0;

            System.Diagnostics.Debug.Assert(n > 0, "CMatrixTRSafeSolve: incorrect N!");
            System.Diagnostics.Debug.Assert(trans == 0 | trans == 1 | trans == 2, "CMatrixTRSafeSolve: incorrect Trans!");
            result = true;
            lnmax = Math.Log(AP.Math.MaxRealNumber);

            //
            // Quick return if possible
            //
            if (n <= 0)
            {
                return result;
            }

            //
            // Load norms: right part and X
            //
            nrmb = 0;
            for (i = 0; i <= n - 1; i++)
            {
                nrmb = Math.Max(nrmb, AP.Math.AbsComplex(x[i]));
            }
            nrmx = 0;

            //
            // Solve
            //
            tmp = new AP.Complex[n];
            result = true;
            if (isupper & trans == 0)
            {

                //
                // U*x = b
                //
                for (i = n - 1; i >= 0; i--)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = a[i, i] * sa;
                    }
                    if (i < n - 1)
                    {
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            tmp[i_] = sa * a[i, i_];
                        }
                        vc = 0.0;
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            vc += tmp[i_] * x[i_];
                        }
                        beta = x[i] - vc;
                    }
                    else
                    {
                        beta = x[i];
                    }

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;
                }
                return result;
            }
            if (!isupper & trans == 0)
            {

                //
                // L*x = b
                //
                for (i = 0; i <= n - 1; i++)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = a[i, i] * sa;
                    }
                    if (i > 0)
                    {
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            tmp[i_] = sa * a[i, i_];
                        }
                        vc = 0.0;
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            vc += tmp[i_] * x[i_];
                        }
                        beta = x[i] - vc;
                    }
                    else
                    {
                        beta = x[i];
                    }

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;
                }
                return result;
            }
            if (isupper & trans == 1)
            {

                //
                // U^T*x = b
                //
                for (i = 0; i <= n - 1; i++)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = a[i, i] * sa;
                    }
                    beta = x[i];

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;

                    //
                    // update the rest of right part
                    //
                    if (i < n - 1)
                    {
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            tmp[i_] = sa * a[i, i_];
                        }
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            x[i_] = x[i_] - vc * tmp[i_];
                        }
                    }
                }
                return result;
            }
            if (!isupper & trans == 1)
            {

                //
                // L^T*x = b
                //
                for (i = n - 1; i >= 0; i--)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = a[i, i] * sa;
                    }
                    beta = x[i];

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;

                    //
                    // update the rest of right part
                    //
                    if (i > 0)
                    {
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            tmp[i_] = sa * a[i, i_];
                        }
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            x[i_] = x[i_] - vc * tmp[i_];
                        }
                    }
                }
                return result;
            }
            if (isupper & trans == 2)
            {

                //
                // U^H*x = b
                //
                for (i = 0; i <= n - 1; i++)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = AP.Math.Conj(a[i, i]) * sa;
                    }
                    beta = x[i];

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;

                    //
                    // update the rest of right part
                    //
                    if (i < n - 1)
                    {
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            tmp[i_] = sa * AP.Math.Conj(a[i, i_]);
                        }
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            x[i_] = x[i_] - vc * tmp[i_];
                        }
                    }
                }
                return result;
            }
            if (!isupper & trans == 2)
            {

                //
                // L^T*x = b
                //
                for (i = n - 1; i >= 0; i--)
                {

                    //
                    // Task is reduced to alpha*x[i] = beta
                    //
                    if (isunit)
                    {
                        alpha = sa;
                    }
                    else
                    {
                        alpha = AP.Math.Conj(a[i, i]) * sa;
                    }
                    beta = x[i];

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref vc);
                    if (!result)
                    {
                        return result;
                    }
                    x[i] = vc;

                    //
                    // update the rest of right part
                    //
                    if (i > 0)
                    {
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            tmp[i_] = sa * AP.Math.Conj(a[i, i_]);
                        }
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            x[i_] = x[i_] - vc * tmp[i_];
                        }
                    }
                }
                return result;
            }
            result = false;
            return result;
        }