Пример #1
0
    public static void zppdi(ref Complex[] ap, int n, ref double[] det, int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZPPDI: determinant, inverse of a complex hermitian positive definite matrix.
    //
    //  Discussion:
    //
    //    The matrix is assumed to have been factored by ZPPCO or ZPPFA.
    //
    //    A division by zero will occur if the input factor contains
    //    a zero on the diagonal and the inverse is requested.
    //    It will not occur if the subroutines are called correctly
    //    and if ZPOCO or ZPOFA has set INFO == 0.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, complex <double> A[(N*(N+1))/2]; on input, the output from ZPPCO
    //    or ZPPFA.  On output, the upper triangular half of the inverse.
    //    The strict lower triangle is unaltered.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Output, double DET[2], the determinant of original matrix if requested.
    //    Otherwise not referenced.  Determinant = DET(1) * 10.0**DET(2)
    //    with 1.0 <= DET(1) < 10.0 or DET(1) == 0.0.
    //
    //    Input, int JOB.
    //    11, both determinant and inverse.
    //    01, inverse only.
    //    10, determinant only.
    //
    {
        //
        //  Compute determinant.
        //
        if (job / 10 != 0)
        {
            det[0] = 1.0;
            det[1] = 0.0;
            int ii = 0;

            int i;
            for (i = 1; i <= n; i++)
            {
                ii    += i;
                det[0] = det[0] * ap[ii - 1].Real * ap[ii - 1].Real;

                if (det[0] == 0.0)
                {
                    break;
                }

                while (det[0] < 1.0)
                {
                    det[0] *= 10.0;
                    det[1] -= 1.0;
                }

                while (10.0 <= det[0])
                {
                    det[0] /= 10.0;
                    det[1] += 1.0;
                }
            }
        }

        //
        //  Compute inverse ( R ).
        //
        if (job % 10 == 0)
        {
            return;
        }

        int kk = 0;

        int     k1;
        int     kj;
        int     k;
        Complex t;
        int     j;
        int     j1;

        for (k = 1; k <= n; k++)
        {
            k1         = kk + 1;
            kk        += k;
            ap[kk - 1] = new Complex(1.0, 0.0) / ap[kk - 1];
            t          = -ap[kk - 1];
            BLAS1Z.zscal(k - 1, t, ref ap, 1, index: +k1 - 1);
            int kp1 = k + 1;
            j1 = kk + 1;
            kj = kk + k;

            for (j = kp1; j <= n; j++)
            {
                t          = ap[kj - 1];
                ap[kj - 1] = new Complex(0.0, 0.0);
                BLAS1Z.zaxpy(k, t, ap, 1, ref ap, 1, xIndex: +k1 - 1, yIndex: +j1 - 1);
                j1 += j;
                kj += j;
            }
        }

        //
        //  Form inverse ( R ) * hermitian ( inverse ( R ) ).
        //
        int jj = 0;

        for (j = 1; j <= n; j++)
        {
            j1  = jj + 1;
            jj += j;
            k1  = 1;
            kj  = j1;

            for (k = 1; k <= j - 1; k++)
            {
                t = Complex.Conjugate(ap[kj - 1]);
                BLAS1Z.zaxpy(k, t, ap, 1, ref ap, 1, xIndex: +j1 - 1, yIndex: k1 - 1);
                k1 += k;
                kj += 1;
            }

            t = Complex.Conjugate(ap[jj - 1]);
            BLAS1Z.zscal(j, t, ref ap, 1, index: +j1 - 1);
        }
    }
Пример #2
0
    public static void zpodi(ref Complex[] a, int lda, int n, ref double[] det, int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZPODI: determinant, inverse of a complex hermitian positive definite matrix.
    //
    //  Discussion:
    //
    //    The matrix is assumed to have been factored by ZPOCO, ZPOFA or ZQRDC.
    //
    //    A division by zero will occur if the input factor contains
    //    a zero on the diagonal and the inverse is requested.
    //    It will not occur if the subroutines are called correctly
    //    and if ZPOCO or ZPOFA has set INFO == 0.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, Complex A[LDA*N]; on input, the output A from ZPOCO or
    //    ZPOFA, or the output X from ZQRDC.  On output, if ZPOCO or ZPOFA was
    //    used to factor A, then ZPODI produces the upper half of inverse(A).
    //    If ZQRDC was used to decompose X, then ZPODI produces the upper half
    //    of inverse(hermitian(X)*X) where hermitian(X) is the conjugate transpose.
    //    Elements of A below the diagonal are unchanged.
    //    If the units digit of JOB is zero, A is unchanged.
    //
    //    Input, int LDA, the leading dimension of A.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Output, double DET[2], if requested, the determinant of A or of
    //    hermitian(X)*X.  Determinant = DET(1) * 10.0**DET(2) with
    //    1.0 <= abs ( DET(1) ) < 10.0 or DET(1) = 0.0.
    //
    //    Input, int JOB.
    //    11, both determinant and inverse.
    //    01, inverse only.
    //    10, determinant only.
    //
    {
        //
        //  Compute determinant
        //
        if (job / 10 != 0)
        {
            det[0] = 1.0;
            det[1] = 0.0;

            int i;
            for (i = 0; i < n; i++)
            {
                det[0] = det[0] * a[i + i * lda].Real * a[i + i * lda].Real;

                if (det[0] == 0.0)
                {
                    break;
                }

                while (det[0] < 1.0)
                {
                    det[0] *= 10.0;
                    det[1] -= 1.0;
                }

                while (10.0 <= det[0])
                {
                    det[0] /= 10.0;
                    det[1] += 1.0;
                }
            }
        }

        //
        //  Compute inverse(R).
        //
        if (job % 10 == 0)
        {
            return;
        }

        int     j;
        int     k;
        Complex t;

        for (k = 1; k <= n; k++)
        {
            a[k - 1 + (k - 1) * lda] = new Complex(1.0, 0.0) / a[k - 1 + (k - 1) * lda];
            t = -a[k - 1 + (k - 1) * lda];
            BLAS1Z.zscal(k - 1, t, ref a, 1, index: +0 + (k - 1) * lda);

            for (j = k + 1; j <= n; j++)
            {
                t = a[k - 1 + (j - 1) * lda];
                a[k - 1 + (j - 1) * lda] = new Complex(0.0, 0.0);
                BLAS1Z.zaxpy(k, t, a, 1, ref a, 1, xIndex: +0 + (k - 1) * lda, yIndex: +0 + (j - 1) * lda);
            }
        }

        //
        //  Form inverse(R) * hermitian(inverse(R)).
        //
        for (j = 1; j <= n; j++)
        {
            for (k = 1; k <= j - 1; k++)
            {
                t = Complex.Conjugate(a[k - 1 + (j - 1) * lda]);
                BLAS1Z.zaxpy(k, t, a, 1, ref a, 1, xIndex: +0 + (j - 1) * lda, yIndex: +0 + (k - 1) * lda);
            }

            t = Complex.Conjugate(a[j - 1 + (j - 1) * lda]);
            BLAS1Z.zscal(j, t, ref a, 1, index: +0 + (j - 1) * lda);
        }
    }
Пример #3
0
    public static int zgbfa(ref Complex[] abd, int lda, int n, int ml, int mu, ref int[] ipvt)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZGBFA factors a complex band matrix by elimination.
    //
    //  Discussion:
    //
    //    ZGBFA is usually called by ZGBCO, but it can be called
    //    directly with a saving in time if RCOND is not needed.
    //
    //  Band storage:
    //
    //    If A is a band matrix, the following program segment
    //    will set up the input.
    //
    //      ml = (band width below the diagonal)
    //      mu = (band width above the diagonal)
    //      m = ml + mu + 1
    //      do j = 1, n
    //        i1 = max ( 1, j - mu )
    //        i2 = min ( n, j + ml )
    //        do i = i1, i2
    //          k = i - j + m
    //          abd(k,j) = a(i,j)
    //        end do
    //      end do
    //
    //    This uses rows ML+1 through 2*ML+MU+1 of ABD.
    //    In addition, the first ML rows in ABD are used for
    //    elements generated during the triangularization.
    //    The total number of rows needed in ABD is 2*ML+MU+1.
    //    The ML+MU by ML+MU upper left triangle and the
    //    ML by ML lower right triangle are not referenced.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, new Complex ABD[LDA*N], on input, contains the matrix in
    //    band storage.  The columns of the matrix are stored in the columns
    //    of ABD and the diagonals of the matrix are stored in rows ML+1
    //    through 2*ML+MU+1 of ABD.  On output, an upper triangular matrix
    //    in band storage and the multipliers which were used to obtain it.
    //    The factorization can be written A = L*U where L is a product of
    //    permutation and unit lower triangular matrices and U is upper triangular.
    //
    //    Input, int LDA, the leading dimension of ABD.
    //    LDA must be at least 2*ML+MU+1.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int ML, the number of diagonals below the main diagonal.
    //    0 <= ML < N.
    //
    //    Input, int MU, the number of diagonals above the main diagonal.
    //    0 <= MU < N.  More efficient if ML <= MU.
    //
    //    Output, int IPVT[N], the pivot indices.
    //
    //    Output, int ZGBFA.
    //    0, normal value.
    //    K, if U(K,K) == 0.0.  This is not an error condition for this
    //    subroutine, but it does indicate that ZGBSL will divide by zero if
    //    called.  Use RCOND in ZGBCO for a reliable indication of singularity.
    //
    {
        int i;
        int jz;
        int k;

        int m    = ml + mu + 1;
        int info = 0;
        //
        //  Zero initial fill-in columns.
        //
        int j0 = mu + 2;
        int j1 = Math.Min(n, m) - 1;

        for (jz = j0; jz <= j1; jz++)
        {
            int i0 = m + 1 - jz;
            for (i = i0; i <= ml; i++)
            {
                abd[i - 1 + (jz - 1) * lda] = new Complex(0.0, 0.0);
            }
        }

        jz = j1;
        int ju = 0;

        //
        //  Gaussian elimination with partial pivoting.
        //
        for (k = 1; k <= n - 1; k++)
        {
            //
            //  Zero next fill-in column
            //
            jz += 1;
            if (jz <= n)
            {
                for (i = 1; i <= ml; i++)
                {
                    abd[i - 1 + (jz - 1) * lda] = new Complex(0.0, 0.0);
                }
            }

            //
            //  Find L = pivot index.
            //
            int lm = Math.Min(ml, n - k);
            int l  = BLAS1Z.izamax(lm + 1, abd, 1, index: +m - 1 + (k - 1) * lda) + m - 1;
            ipvt[k - 1] = l + k - m;
            //
            //  Zero pivot implies this column already triangularized.
            //
            if (typeMethods.zabs1(abd[l - 1 + (k - 1) * lda]) == 0.0)
            {
                info = k;
                continue;
            }

            //
            //  Interchange if necessary.
            //
            Complex t;
            if (l != m)
            {
                t = abd[l - 1 + (k - 1) * lda];
                abd[l - 1 + (k - 1) * lda] = abd[m - 1 + (k - 1) * lda];
                abd[m - 1 + (k - 1) * lda] = t;
            }

            //
            //  Compute multipliers.
            //
            t = -new Complex(1.0, 0.0) / abd[m - 1 + (k - 1) * lda];
            BLAS1Z.zscal(lm, t, ref abd, 1, index: +m + (k - 1) * lda);
            //
            //  Row elimination with column indexing.
            //
            ju = Math.Min(Math.Max(ju, mu + ipvt[k - 1]), n);
            int mm = m;

            int j;
            for (j = k + 1; j <= ju; j++)
            {
                l  -= 1;
                mm -= 1;
                t   = abd[l - 1 + (j - 1) * lda];
                if (l != mm)
                {
                    abd[l - 1 + (j - 1) * lda]  = abd[mm - 1 + (j - 1) * lda];
                    abd[mm - 1 + (j - 1) * lda] = t;
                }

                BLAS1Z.zaxpy(lm, t, abd, 1, ref abd, 1, xIndex: +m + (k - 1) * lda, yIndex: +mm + (j - 1) * lda);
            }
        }

        ipvt[n - 1] = n;

        if (typeMethods.zabs1(abd[m - 1 + (n - 1) * lda]) == 0.0)
        {
            info = n;
        }

        return(info);
    }
Пример #4
0
    public static void zqrdc(ref Complex[] x, int ldx, int n, int p,
                             ref Complex[] qraux, ref int[] ipvt, int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZQRDC computes the QR factorization of an N by P complex <double> matrix.
    //
    //  Discussion:
    //
    //    ZQRDC uses Householder transformations to compute the QR factorization
    //    of an N by P matrix X.  Column pivoting based on the 2-norms of the
    //    reduced columns may be performed at the user's option.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, complex <double> X[LDX*P]; on input, the matrix whose decomposition
    //    is to be computed.  On output, the upper triangle contains the upper
    //    triangular matrix R of the QR factorization.  Below its diagonal, X
    //    contains information from which the unitary part of the decomposition
    //    can be recovered.  If pivoting has been requested, the decomposition is
    //    not that of the original matrix X, but that of X with its columns
    //    permuted as described by IPVT.
    //
    //    Input, int LDX, the leading dimension of X.  N <= LDX.
    //
    //    Input, int N, the number of rows of the matrix.
    //
    //    Input, int P, the number of columns in the matrix X.
    //
    //    Output, complex <double> QRAUX[P], further information required to recover
    //    the unitary part of the decomposition.
    //
    //    Input/output, int IPVT[P]; on input, ints that control the
    //    selection of the pivot columns.  The K-th column X(K) of X is placed
    //    in one of three classes according to the value of IPVT(K):
    //      IPVT(K) > 0, then X(K) is an initial column.
    //      IPVT(K) == 0, then X(K) is a free column.
    //      IPVT(K) < 0, then X(K) is a final column.
    //    Before the decomposition is computed, initial columns are moved to the
    //    beginning of the array X and final columns to the end.  Both initial
    //    and final columns are frozen in place during the computation and only
    //    free columns are moved.  At the K-th stage of the reduction, if X(K)
    //    is occupied by a free column it is interchanged with the free column
    //    of largest reduced norm.
    //    On output, IPVT(K) contains the index of the column of the
    //    original matrix that has been interchanged into
    //    the K-th column, if pivoting was requested.
    //    IPVT is not referenced if JOB == 0.
    //
    //    Input, int JOB, initiates column pivoting.
    //    0, no pivoting is done.
    //    nonzero, pivoting is done.
    //
    {
        int itemp;
        int j;
        int l;

        int pl = 1;
        int pu = 0;

        Complex[] work = new Complex [p];

        if (job != 0)
        {
            //
            //  Pivoting has been requested.  Rearrange the columns according to IPVT.
            //
            for (j = 1; j <= p; j++)
            {
                bool swapj = 0 < ipvt[j - 1];
                bool negj  = ipvt[j - 1] < 0;

                ipvt[j - 1] = negj switch
                {
                    true => - j,
                    _ => j
                };

                switch (swapj)
                {
                case true:
                {
                    if (j != pl)
                    {
                        BLAS1Z.zswap(n, ref x, 1, ref x, 1, xIndex: +0 + (pl - 1) * ldx, yIndex: +0 + (j - 1) * ldx);
                    }

                    ipvt[j - 1]  = ipvt[pl - 1];
                    ipvt[pl - 1] = j;
                    pl          += 1;
                    break;
                }
                }
            }

            pu = p;

            int jj;
            for (jj = 1; jj <= p; jj++)
            {
                j = p - jj + 1;

                switch (ipvt[j - 1])
                {
                case < 0:
                {
                    ipvt[j - 1] = -ipvt[j - 1];

                    if (j != pu)
                    {
                        BLAS1Z.zswap(n, ref x, 1, ref x, 1, xIndex: +0 + (pu - 1) * ldx, yIndex: +0 + (j - 1) * ldx);

                        itemp        = ipvt[pu - 1];
                        ipvt[pu - 1] = ipvt[j - 1];
                        ipvt[j - 1]  = itemp;
                    }

                    pu -= 1;
                    break;
                }
                }
            }
        }

        //
        //  Compute the norms of the free columns.
        //
        for (j = pl; j <= pu; j++)
        {
            qraux[j - 1] = new Complex(BLAS1Z.dznrm2(n, x, 1, index: +0 + (j - 1) * ldx), 0.0);
            work[j - 1]  = qraux[j - 1];
        }

        //
        //  Perform the Householder reduction of X.
        //
        int lup = Math.Min(n, p);

        for (l = 1; l <= lup; l++)
        {
            //
            //  Locate the column of largest norm and bring it
            //  into the pivot position.
            //
            if (pl <= l && l < pu)
            {
                double maxnrm = 0.0;
                int    maxj   = l;

                for (j = l; j <= pu; j++)
                {
                    if (!(maxnrm < qraux[j - 1].Real))
                    {
                        continue;
                    }

                    maxnrm = qraux[j - 1].Real;
                    maxj   = j;
                }

                if (maxj != l)
                {
                    BLAS1Z.zswap(n, ref x, 1, ref x, 1, xIndex: +0 + (l - 1) * ldx, yIndex: +0 + (maxj - 1) * ldx);
                    qraux[maxj - 1] = qraux[l - 1];
                    work[maxj - 1]  = work[l - 1];

                    itemp          = ipvt[maxj - 1];
                    ipvt[maxj - 1] = ipvt[l - 1];
                    ipvt[l - 1]    = itemp;
                }
            }

            qraux[l - 1] = new Complex(0.0, 0.0);

            if (l == n)
            {
                continue;
            }

            //
            //  Compute the Householder transformation for column L.
            //
            Complex nrmxl = new(BLAS1Z.dznrm2(n - l + 1, x, 1, index: +l - 1 + (l - 1) * ldx), 0.0);

            if (typeMethods.zabs1(nrmxl) == 0.0)
            {
                continue;
            }

            if (typeMethods.zabs1(x[l - 1 + (l - 1) * ldx]) != 0.0)
            {
                nrmxl = typeMethods.zsign2(nrmxl, x[l - 1 + (l - 1) * ldx]);
            }

            Complex t = new Complex(1.0, 0.0) / nrmxl;
            BLAS1Z.zscal(n - l + 1, t, ref x, 1, index: +l - 1 + (l - 1) * ldx);
            x[l - 1 + (l - 1) * ldx] = new Complex(1.0, 0.0) + x[l - 1 + (l - 1) * ldx];
            //
            //  Apply the transformation to the remaining columns,
            //  updating the norms.
            //
            for (j = l + 1; j <= p; j++)
            {
                t = -BLAS1Z.zdotc(n - l + 1, x, 1, x, 1, xIndex: +l - 1 + (l - 1) * ldx, yIndex: +l - 1 + (j - 1) * ldx)
                    / x[l - 1 + (l - 1) * ldx];
                BLAS1Z.zaxpy(n - l + 1, t, x, 1, ref x, 1, xIndex: +l - 1 + (l - 1) * ldx, yIndex: +l - 1 + (j - 1) * ldx);

                if (j < pl || pu < j)
                {
                    continue;
                }

                if (typeMethods.zabs1(qraux[j - 1]) == 0.0)
                {
                    continue;
                }

                double tt = 1.0 - Math.Pow(Complex.Abs(x[l - 1 + (j - 1) * ldx]) / qraux[j - 1].Real, 2);
                tt = Math.Max(tt, 0.0);
                t  = new Complex(tt, 0.0);
                tt = 1.0 + 0.05 * tt
                     * Math.Pow(qraux[j - 1].Real / work[j - 1].Real, 2);

                if (Math.Abs(tt - 1.0) > double.Epsilon)
                {
                    qraux[j - 1] *= Complex.Sqrt(t);
                }
                else
                {
                    qraux[j - 1] =
                        new Complex(BLAS1Z.dznrm2(n - l, x, 1, index: +l + (j - 1) * ldx), 0.0);
                    work[j - 1] = qraux[j - 1];
                }
            }

            //
            //  Save the transformation.
            //
            qraux[l - 1]             = x[l - 1 + (l - 1) * ldx];
            x[l - 1 + (l - 1) * ldx] = -nrmxl;
        }
    }
}
Пример #5
0
    public static int zgefa(ref Complex[] a, int lda, int n, ref int[] ipvt)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZGEFA factors a complex matrix by Gaussian elimination.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, Complex A[LDA*N]; on input, the matrix to be factored.
    //    On output, an upper triangular matrix and the multipliers which were
    //    used to obtain it.  The factorization can be written A = L*U where
    //    L is a product of permutation and unit lower triangular matrices and
    //    U is upper triangular.
    //
    //    Input, int LDA, the leading dimension of A.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Output, int IPVT[N], the pivot indices.
    //
    //    Output, int ZGEFA,
    //    0, normal value.
    //    K, if U(K,K) == 0.0.  This is not an error condition for this
    //    subroutine, but it does indicate that ZGESL or ZGEDI will divide by zero
    //    if called.  Use RCOND in ZGECO for a reliable indication of singularity.
    //
    {
        int k;
        //
        //  Gaussian elimination with partial pivoting.
        //
        int info = 0;

        for (k = 1; k <= n - 1; k++)
        {
            //
            //  Find L = pivot index.
            //
            int l = BLAS1Z.izamax(n - k + 1, a, 1, index: +(k - 1) + (k - 1) * lda) + k - 1;
            ipvt[k - 1] = l;
            //
            //  Zero pivot implies this column already triangularized.
            //
            if (typeMethods.zabs1(a[l - 1 + (k - 1) * lda]) == 0.0)
            {
                info = k;
                continue;
            }

            //
            //  Interchange if necessary.
            //
            Complex t;
            if (l != k)
            {
                t = a[l - 1 + (k - 1) * lda];
                a[l - 1 + (k - 1) * lda] = a[k - 1 + (k - 1) * lda];
                a[k - 1 + (k - 1) * lda] = t;
            }

            //
            //  Compute multipliers
            //
            t = -new Complex(1.0, 0.0) / a[k - 1 + (k - 1) * lda];
            BLAS1Z.zscal(n - k, t, ref a, 1, index: +k + (k - 1) * lda);
            //
            //  Row elimination with column indexing
            //
            int j;
            for (j = k + 1; j <= n; j++)
            {
                t = a[l - 1 + (j - 1) * lda];
                if (l != k)
                {
                    a[l - 1 + (j - 1) * lda] = a[k - 1 + (j - 1) * lda];
                    a[k - 1 + (j - 1) * lda] = t;
                }

                BLAS1Z.zaxpy(n - k, t, a, 1, ref a, 1, xIndex: +k + (k - 1) * lda, yIndex: +k + (j - 1) * lda);
            }
        }

        ipvt[n - 1] = n;

        if (typeMethods.zabs1(a[n - 1 + (n - 1) * lda]) == 0.0)
        {
            info = n;
        }

        return(info);
    }
Пример #6
0
    public static void zgedi(ref Complex[] a, int lda, int n, int[] ipvt,
                             ref Complex[] det, int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZGEDI computes the determinant and inverse of a matrix.
    //
    //  Discussion:
    //
    //    The matrix must have been factored by ZGECO or ZGEFA.
    //
    //    A division by zero will occur if the input factor contains
    //    a zero on the diagonal and the inverse is requested.
    //    It will not occur if the subroutines are called correctly
    //    and if ZGECO has set 0.0 < RCOND or ZGEFA has set
    //    INFO == 0.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, Complex A[LDA*N]; on input, the factor information
    //    from ZGECO or ZGEFA.  On output, the inverse matrix, if it
    //    was requested,
    //
    //    Input, int LDA, the leading dimension of A.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int IPVT[N], the pivot vector from ZGECO or ZGEFA.
    //
    //    Output, Complex DET[2], the determinant of the original matrix,
    //    if requested.  Otherwise not referenced.
    //    Determinant = DET(1) * 10.0**DET(2) with
    //    1.0 <= typeMethods.zabs1 ( DET(1) ) < 10.0 or DET(1) == 0.0.
    //    Also, DET(2) is strictly real.
    //
    //    Input, int JOB.
    //    11, both determinant and inverse.
    //    01, inverse only.
    //    10, determinant only.
    //
    {
        int i;

        //
        //  Compute the determinant.
        //
        if (job / 10 != 0)
        {
            det[0] = new Complex(1.0, 0.0);
            det[1] = new Complex(0.0, 0.0);

            for (i = 1; i <= n; i++)
            {
                if (ipvt[i - 1] != i)
                {
                    det[0] = -det[0];
                }

                det[0] = a[i - 1 + (i - 1) * lda] * det[0];

                if (typeMethods.zabs1(det[0]) == 0.0)
                {
                    break;
                }

                while (typeMethods.zabs1(det[0]) < 1.0)
                {
                    det[0] *= new Complex(10.0, 0.0);
                    det[1] -= new Complex(1.0, 0.0);
                }

                while (10.0 <= typeMethods.zabs1(det[0]))
                {
                    det[0] /= new Complex(10.0, 0.0);
                    det[1] += new Complex(1.0, 0.0);
                }
            }
        }

        //
        //  Compute inverse(U).
        //
        if (job % 10 == 0)
        {
            return;
        }

        Complex[] work = new Complex[n];

        int     j;
        Complex t;
        int     k;

        for (k = 1; k <= n; k++)
        {
            a[k - 1 + (k - 1) * lda] = new Complex(1.0, 0.0) / a[k - 1 + (k - 1) * lda];
            t = -a[k - 1 + (k - 1) * lda];
            BLAS1Z.zscal(k - 1, t, ref a, 1, index: +0 + (k - 1) * lda);

            for (j = k + 1; j <= n; j++)
            {
                t = a[k - 1 + (j - 1) * lda];
                a[k - 1 + (j - 1) * lda] = new Complex(0.0, 0.0);
                BLAS1Z.zaxpy(k, t, a, 1, ref a, 1, xIndex: +0 + (k - 1) * lda, yIndex: +0 + (j - 1) * lda);
            }
        }

        //
        //  Form inverse(U) * inverse(L).
        //
        for (k = n - 1; 1 <= k; k--)
        {
            for (i = k + 1; i <= n; i++)
            {
                work[i - 1] = a[i - 1 + (k - 1) * lda];
                a[i - 1 + (k - 1) * lda] = new Complex(0.0, 0.0);
            }

            for (j = k + 1; j <= n; j++)
            {
                t = work[j - 1];
                BLAS1Z.zaxpy(n, t, a, 1, ref a, 1, xIndex: +0 + (j - 1) * lda, yIndex: +0 + (k - 1) * lda);
            }

            int l = ipvt[k - 1];

            if (l != k)
            {
                BLAS1Z.zswap(n, ref a, 1, ref a, 1, xIndex: +0 + (k - 1) * lda, yIndex: +0 + (l - 1) * lda);
            }
        }
    }
Пример #7
0
    public static int ztrdi(ref Complex[] t, int ldt, int n, ref Complex[] det,
                            int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZTRDI computes the determinant and inverse of a complex triangular matrix.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    21 May 2006
    //
    //  Author:
    //
    //    C++ version by John Burkardt
    //
    //  Reference:
    //
    //    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
    //    LINPACK User's Guide,
    //    SIAM, (Society for Industrial and Applied Mathematics),
    //    3600 University City Science Center,
    //    Philadelphia, PA, 19104-2688.
    //
    //  Parameters:
    //
    //    Input/output, Complex T[LDT*N], the triangular matrix.  The zero
    //    elements of the matrix are not referenced, and the corresponding
    //    elements of the array can be used to store other information.
    //    On output, if an inverse was requested, then T has been overwritten
    //    by its inverse.
    //
    //    Input, int LDT, the leading dimension of T.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int JOB.
    //    010, no determinant,    inverse, matrix is lower triangular.
    //    011, no determinant,    inverse, matrix is upper triangular.
    //    100,    determinant, no inverse.
    //    110,    determinant,    inverse, matrix is lower triangular.
    //    111,    determinant,    inverse, matrix is upper triangular.
    //
    //    Output, Complex DET[2], the determinant of the original matrix,
    //    if requested.  Otherwise not referenced.
    //    Determinant = DET(1) * 10.0**DET(2) with 1.0 <= typeMethods.zabs1 ( DET(1) ) < 10.0
    //    or DET(1) == 0.0.  Also, DET(2) is strictly real.
    //
    //    Output, int ZTRDI.
    //    0, an inverse was requested and the matrix is nonsingular.
    //    K, an inverse was requested, but the K-th diagonal element
    //    of T is zero.
    //
    {
        int info = 0;

        if (job / 100 != 0)
        {
            det[0] = new Complex(1.0, 0.0);
            det[1] = new Complex(0.0, 0.0);

            int i;
            for (i = 0; i < n; i++)
            {
                det[0] *= t[i + i * ldt];

                if (typeMethods.zabs1(det[0]) == 0.0)
                {
                    break;
                }

                while (typeMethods.zabs1(det[0]) < 1.0)
                {
                    det[0] *= new Complex(10.0, 0.0);
                    det[1] -= new Complex(1.0, 0.0);
                }

                while (10.0 <= typeMethods.zabs1(det[0]))
                {
                    det[0] /= new Complex(10.0, 0.0);
                    det[1] += new Complex(1.0, 0.0);
                }
            }
        }

        //
        //  Compute inverse of upper triangular matrix.
        //
        if (job / 10 % 10 == 0)
        {
            return(info);
        }

        Complex temp;
        int     j;
        int     k;

        if (job % 10 != 0)
        {
            info = 0;

            for (k = 0; k < n; k++)
            {
                if (typeMethods.zabs1(t[k + k * ldt]) == 0.0)
                {
                    info = k + 1;
                    break;
                }

                t[k + k * ldt] = new Complex(1.0, 0.0) / t[k + k * ldt];
                temp           = -t[k + k * ldt];
                BLAS1Z.zscal(k, temp, ref t, 1, index: +0 + k * ldt);

                for (j = k + 1; j < n; j++)
                {
                    temp           = t[k + j * ldt];
                    t[k + j * ldt] = new Complex(0.0, 0.0);
                    BLAS1Z.zaxpy(k + 1, temp, t, 1, ref t, 1, xIndex: +0 + k * ldt, yIndex: +0 + j * ldt);
                }
            }
        }
        //
        //  Compute inverse of lower triangular matrix.
        //
        else
        {
            info = 0;

            for (k = n - 1; 0 <= k; k--)
            {
                if (typeMethods.zabs1(t[k + k * ldt]) == 0.0)
                {
                    info = k + 1;
                    break;
                }

                t[k + k * ldt] = new Complex(1.0, 0.0) / t[k + k * ldt];

                if (k != n - 1)
                {
                    temp = -t[k + k * ldt];
                    BLAS1Z.zscal(n - k - 1, temp, ref t, 1, index: +k + 1 + k * ldt);
                }

                for (j = 0; j < k; j++)
                {
                    temp           = t[k + j * ldt];
                    t[k + j * ldt] = new Complex(0.0, 0.0);
                    BLAS1Z.zaxpy(n - k, temp, t, 1, ref t, 1, xIndex: +k + k * ldt, yIndex: +k + j * ldt);
                }
            }
        }

        return(info);
    }