예제 #1
0
    public static void zsisl(Complex[] a, int lda, int n, int[] ipvt,
                             ref Complex[] b)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZSISL solves a complex symmetric system that was factored by ZSIFA.
    //
    //  Discussion:
    //
    //    A division by zero may occur if ZSICO has set RCOND == 0.0
    //    or ZSIFA 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, Complex A[LDA*N], the output from ZSICO or ZSIFA.
    //
    //    Input, int LDA, the leading dimension of A.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int IPVT[N], the pivot vector from ZSICO or ZSIFA.
    //
    //    Input/output, Complex B[N].  On input, the right hand side.
    //    On output, the solution.
    //
    {
        int     kp;
        Complex t;
        //
        //  Loop backward applying the transformations and D inverse to B.
        //
        int k = n;

        while (0 < k)
        {
            switch (ipvt[k - 1])
            {
            //
            //  1 x 1 pivot block.
            //
            case >= 0:
            {
                if (k != 1)
                {
                    kp = ipvt[k - 1];

                    if (kp != k)
                    {
                        t         = b[k - 1];
                        b[k - 1]  = b[kp - 1];
                        b[kp - 1] = t;
                    }

                    BLAS1Z.zaxpy(k - 1, b[k - 1], a, 1, ref b, 1, xIndex: +0 + (k - 1) * lda);
                }

                b[k - 1] /= a[k - 1 + (k - 1) * lda];
                k        -= 1;
                break;
            }

            //
            default:
            {
                if (k != 2)
                {
                    kp = Math.Abs(ipvt[k - 1]);

                    if (kp != k - 1)
                    {
                        t         = b[k - 2];
                        b[k - 2]  = b[kp - 1];
                        b[kp - 1] = t;
                    }

                    BLAS1Z.zaxpy(k - 2, b[k - 1], a, 1, ref b, 1, xIndex: +0 + (k - 1) * lda);
                    BLAS1Z.zaxpy(k - 2, b[k - 2], a, 1, ref b, 1, xIndex: +0 + (k - 2) * lda);
                }

                Complex ak    = a[k - 1 + (k - 1) * lda] / a[k - 2 + (k - 1) * lda];
                Complex akm1  = a[k - 2 + (k - 2) * lda] / a[k - 2 + (k - 1) * lda];
                Complex bk    = b[k - 1] / a[k - 2 + (k - 1) * lda];
                Complex bkm1  = b[k - 2] / a[k - 2 + (k - 1) * lda];
                Complex denom = ak * akm1 - new Complex(1.0, 0.0);
                b[k - 1] = (akm1 * bk - bkm1) / denom;
                b[k - 2] = (ak * bkm1 - bk) / denom;
                k       -= 2;
                break;
            }
            }
        }

        //
        //  Loop forward applying the transformations.
        //
        k = 1;

        while (k <= n)
        {
            switch (ipvt[k - 1])
            {
            case >= 0:
            {
                //
                //  1 x 1 pivot block.
                //
                if (k != 1)
                {
                    b[k - 1] += BLAS1Z.zdotu(k - 1, a, 1, b, 1, xIndex: +0 + (k - 1) * lda);
                    kp        = ipvt[k - 1];

                    if (kp != k)
                    {
                        t         = b[k - 1];
                        b[k - 1]  = b[kp - 1];
                        b[kp - 1] = t;
                    }
                }

                k += 1;
                break;
            }

            //
            default:
            {
                if (k != 1)
                {
                    b[k - 1] += BLAS1Z.zdotu(k - 1, a, 1, b, 1, xIndex: +0 + (k - 1) * lda);
                    b[k]     += BLAS1Z.zdotu(k - 1, a, 1, b, 1, xIndex: +0 + k * lda);
                    kp        = Math.Abs(ipvt[k - 1]);

                    if (kp != k)
                    {
                        t         = b[k - 1];
                        b[k - 1]  = b[kp - 1];
                        b[kp - 1] = t;
                    }
                }

                k += 2;
                break;
            }
            }
        }
    }
예제 #2
0
    public static void zspdi(ref Complex[] ap, int n, int[] ipvt, ref Complex[] det,
                             int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZSPDI sets the determinant and inverse of a complex symmetric packed matrix.
    //
    //  Discussion:
    //
    //    ZSPDI uses the factors from ZSPFA.
    //
    //    The matrix is stored in packed form.
    //
    //    A division by zero will occur if the inverse is requested and ZSPCO has
    //    set RCOND to 0.0 or ZSPFA has set INFO nonzero.
    //
    //  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 AP[N*(N+1)/2]; on input, the matrix factors
    //    from ZSPFA.  On output, if the inverse was requested, the upper
    //    triangle of the inverse of the original matrix, stored in packed
    //    form.  The columns of the upper triangle are stored sequentially
    //    in a one-dimensional array.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int IPVT[N], the pivot vector from ZSPFA.
    //
    //    Output, Complex DET[2], the determinant of the original matrix.
    //    Determinant = DET(1) * 10.0**DET(2) with 1.0 <= abs ( DET(1) ) < 10.0
    //    or DET(1) = 0.0.  Also, DET(2) is strictly real.
    //
    //    Input, int JOB, has the decimal expansion AB where
    //    if B != 0, the inverse is computed,
    //    if A != 0, the determinant is computed,
    //    For example, JOB = 11 gives both.
    //
    {
        Complex d;
        int     ik;
        int     ikp1;
        int     k;
        int     kk;
        int     kkp1 = 0;
        Complex t;

        bool noinv = job % 10 == 0;
        bool nodet = job % 100 / 10 == 0;

        switch (nodet)
        {
        case false:
        {
            det[0] = new Complex(1.0, 0.0);
            det[1] = new Complex(0.0, 0.0);
            t      = new Complex(0.0, 0.0);
            ik     = 0;

            for (k = 1; k <= n; k++)
            {
                kk = ik + k;
                d  = ap[kk - 1];
                switch (ipvt[k - 1])
                {
                //
                //  2 by 2 block
                //  Use det (D  T)  =  ( D / T * C - T ) * T
                //          (T  C)
                //  to avoid underflow/overflow troubles.
                //  Take two passes through scaling.  Use T for flag.
                //
                case <= 0 when typeMethods.zabs1(t) == 0.0:
                    ikp1 = ik + k;

                    kkp1 = ikp1 + k;
                    t    = ap[kkp1 - 1];
                    d    = d / t * ap[kkp1] - t;
                    break;

                case <= 0:
                    d = t;
                    t = new Complex(0.0, 0.0);
                    break;
                }

                switch (nodet)
                {
                case false:
                {
                    det[0] *= d;

                    if (typeMethods.zabs1(det[0]) != 0.0)
                    {
                        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);
                        }
                    }

                    break;
                }
                }

                ik += k;
            }

            break;
        }
        }

        switch (noinv)
        {
        //
        //  Compute inverse ( A ).
        //
        case false:
        {
            Complex[] work = new Complex[n];
            k  = 1;
            ik = 0;

            while (k <= n)
            {
                int km1 = k - 1;
                kk   = ik + k;
                ikp1 = ik + k;

                int j;
                int jk;
                int i;
                int ij;
                int kstep;
                switch (ipvt[k - 1])
                {
                case >= 0:
                {
                    //
                    //  1 by 1
                    //
                    ap[kk - 1] = new Complex(1.0, 0.0) / ap[kk - 1];

                    switch (km1)
                    {
                    case >= 1:
                    {
                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = ap[ik + i - 1];
                        }

                        ij = 0;

                        for (j = 1; j <= km1; j++)
                        {
                            jk         = ik + j;
                            ap[jk - 1] = BLAS1Z.zdotu(j, ap, 1, work, 1, xIndex: +ij);
                            BLAS1Z.zaxpy(j - 1, work[j - 1], ap, 1, ref ap, 1, xIndex: +ij, yIndex: +ik);
                            ij += j;
                        }

                        ap[kk - 1] += BLAS1Z.zdotu(km1, work, 1, ap, 1, yIndex: +ik);
                        break;
                    }
                    }

                    kstep = 1;
                    break;
                }

                //
                default:
                {
                    kkp1 = ikp1 + k;
                    t    = ap[kkp1 - 1];
                    Complex ak    = ap[kk - 1] / t;
                    Complex akp1  = ap[kkp1] / t;
                    Complex akkp1 = ap[kkp1 - 1] / t;
                    d            = t * (ak * akp1 - new Complex(1.0, 0.0));
                    ap[kk - 1]   = akp1 / d;
                    ap[kkp1]     = ak / d;
                    ap[kkp1 - 1] = -akkp1 / d;

                    switch (km1)
                    {
                    case >= 1:
                    {
                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = ap[ikp1 - 1];
                        }

                        ij = 0;

                        for (j = 1; j <= km1; j++)
                        {
                            int jkp1 = ikp1 + j;
                            ap[jkp1 - 1] = BLAS1Z.zdotu(j, ap, 1, work, 1, xIndex: +ij);
                            BLAS1Z.zaxpy(j - 1, work[j - 1], ap, 1, ref ap, 1, xIndex: +ij, yIndex: +ikp1);
                            ij += j;
                        }

                        ap[kkp1]     += BLAS1Z.zdotu(km1, work, 1, ap, 1, yIndex: +ikp1);
                        ap[kkp1 - 1] += BLAS1Z.zdotu(km1, ap, 1, ap, 1, xIndex: +ik, yIndex: +ikp1);

                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = ap[ik + i - 1];
                        }

                        ij = 0;

                        for (j = 1; j <= km1; j++)
                        {
                            jk         = ik + j;
                            ap[jk - 1] = BLAS1Z.zdotu(j, ap, 1, work, 1, xIndex: +ij);
                            BLAS1Z.zaxpy(j - 1, work[j - 1], ap, 1, ref ap, 1, xIndex: +ij, yIndex: +ik);
                            ij += j;
                        }

                        ap[kk - 1] += BLAS1Z.zdotu(km1, work, 1, ap, 1, yIndex: +ik);
                        break;
                    }
                    }

                    kstep = 2;
                    break;
                }
                }

                //
                //  Swap.
                //
                int ks = Math.Abs(ipvt[k - 1]);

                if (ks != k)
                {
                    int iks = ks * (ks - 1) / 2;
                    BLAS1Z.zswap(ks, ref ap, 1, ref ap, 1, xIndex: +iks, yIndex: +ik);
                    int ksj = ik + ks;

                    int jb;
                    for (jb = ks; jb <= k; jb++)
                    {
                        j  = k + ks - jb;
                        jk = ik + j;

                        t           = ap[jk - 1];
                        ap[jk - 1]  = ap[ksj - 1];
                        ap[ksj - 1] = t;

                        ksj -= j - 1;
                    }

                    if (kstep != 1)
                    {
                        int kskp1 = ikp1 + ks;

                        t             = ap[kskp1 - 1];
                        ap[kskp1 - 1] = ap[kkp1 - 1];
                        ap[kkp1 - 1]  = t;
                    }
                }

                ik += k;

                ik = kstep switch
                {
                    2 => ik + k + 1,
                    _ => ik
                };

                k += kstep;
            }

            break;
        }
        }
    }
}
예제 #3
0
    public static void zsidi(ref Complex[] a, int lda, int n, int[] ipvt,
                             ref Complex[] det, int job)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    ZSIDI computes the determinant and inverse of a matrix factored by ZSIFA.
    //
    //  Discussion:
    //
    //    It is assumed the complex symmetric matrix has already been factored
    //    by ZSIFA.
    //
    //    A division by zero may occur if the inverse is requested
    //    and ZSICO set RCOND == 0.0 or ZSIFA set INFO nonzero.
    //
    //  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 from ZSIFA.
    //    If the inverse was requested, then on output, A contains the upper triangle
    //    of the inverse of the original matrix.  The strict lower triangle
    //    is never referenced.
    //
    //    Input, int LDA, the leading dimension of A.
    //
    //    Input, int N, the order of the matrix.
    //
    //    Input, int IPVT[N], the pivot vector from ZSIFA.
    //
    //    Output, Complex DET[2], if requested, the determinant of the matrix.
    //    Determinant = DET(1) * 10.0**DET(2) with 1.0 <= abs ( DET(1) ) < 10.0
    //    or DET(1) = 0.0.  Also, DET(2) is strictly real.
    //
    //    Input, int JOB, has the decimal expansion AB where
    //    if B != 0, the inverse is computed,
    //    if A != 0, the determinant is computed,
    //    For example, JOB = 11 gives both.
    //
    {
        Complex d;
        int     k;
        Complex t;

        bool noinv = job % 10 == 0;
        bool nodet = job % 100 / 10 == 0;

        switch (nodet)
        {
        case false:
        {
            det[0] = new Complex(1.0, 0.0);
            det[1] = new Complex(0.0, 0.0);
            t      = new Complex(0.0, 0.0);

            for (k = 1; k <= n; k++)
            {
                d = a[k - 1 + (k - 1) * lda];
                switch (ipvt[k - 1])
                {
                //
                //   2 by 2 block.
                //   Use det ( D  T ) = ( D / T * C - T ) * T
                //           ( T  C )
                //   to avoid underflow/overflow troubles.
                //   Take two passes through scaling.  Use T for flag.
                //
                case <= 0 when typeMethods.zabs1(t) == 0.0:
                    t = a[k - 1 + k * lda];

                    d = d / t * a[k + k * lda] - t;
                    break;

                case <= 0:
                    d = t;
                    t = new Complex(0.0, 0.0);
                    break;
                }

                det[0] *= d;

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

                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);
                }
            }

            break;
        }
        }

        switch (noinv)
        {
        //
        //  Compute inverse ( A ).
        //
        case false:
        {
            Complex[] work = new Complex [n];

            k = 1;

            while (k <= n)
            {
                int km1 = k - 1;
                int kstep;
                int j;
                int i;
                switch (ipvt[k - 1])
                {
                //
                //  1 by 1
                //
                case >= 0:
                {
                    a[k - 1 + (k - 1) * lda] = new Complex(1.0, 0.0) / a[k - 1 + (k - 1) * lda];

                    switch (km1)
                    {
                    case >= 1:
                    {
                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = a[i - 1 + (k - 1) * lda];
                        }

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

                        a[k - 1 + (k - 1) * lda] += BLAS1Z.zdotu(km1, work, 1, a, 1, yIndex: +0 + (k - 1) * lda);
                        break;
                    }
                    }

                    kstep = 1;
                    break;
                }

                //
                default:
                {
                    t = a[k - 1 + k * lda];
                    Complex ak    = a[k - 1 + (k - 1) * lda] / t;
                    Complex akp1  = a[k + k * lda] / t;
                    Complex akkp1 = a[k - 1 + k * lda] / t;
                    d = t * (ak * akp1 - new Complex(1.0, 0.0));
                    a[k - 1 + (k - 1) * lda] = akp1 / d;
                    a[k + k * lda]           = ak / d;
                    a[k - 1 + k * lda]       = -akkp1 / d;

                    switch (km1)
                    {
                    case >= 1:
                    {
                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = a[i - 1 + k * lda];
                        }

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

                        a[k + k * lda]     += BLAS1Z.zdotu(km1, work, 1, a, 1, yIndex: +0 + k * lda);
                        a[k - 1 + k * lda] += BLAS1Z.zdotu(km1, a, 1, a, 1, xIndex: +0 + (k - 1) * lda,
                                                           yIndex: +0 + k * lda);

                        for (i = 1; i <= km1; i++)
                        {
                            work[i - 1] = a[i - 1 + (k - 1) * lda];
                        }

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

                        a[k - 1 + (k - 1) * lda] += BLAS1Z.zdotu(km1, work, 1, a, 1, yIndex: +0 + (k - 1) * lda);
                        break;
                    }
                    }

                    kstep = 2;
                    break;
                }
                }

                //
                //  Swap.
                //
                int ks = Math.Abs(ipvt[k - 1]);

                if (ks != k)
                {
                    BLAS1Z.zswap(ks, ref a, 1, ref a, 1, xIndex: +0 + (ks - 1) * lda, yIndex: +0 + (k - 1) * lda);

                    int jb;
                    for (jb = ks; jb <= k; jb++)
                    {
                        j = k + ks - jb;

                        t = a[j - 1 + (k - 1) * lda];
                        a[j - 1 + (k - 1) * lda]  = a[ks - 1 + (j - 1) * lda];
                        a[ks - 1 + (j - 1) * lda] = t;
                    }

                    if (kstep != 1)
                    {
                        t = a[ks - 1 + k * lda];
                        a[ks - 1 + k * lda] = a[k - 1 + k * lda];
                        a[k - 1 + k * lda]  = t;
                    }
                }

                k += kstep;
            }

            break;
        }
        }
    }