예제 #1
0
        /*************************************************************************
        *  1-dimensional complex cross-correlation.
        *
        *  For given Pattern/Signal returns corr(Pattern,Signal) (non-circular).
        *
        *  Correlation is calculated using reduction to  convolution.  Algorithm with
        *  max(N,N)*log(max(N,N)) complexity is used (see  ConvC1D()  for  more  info
        *  about performance).
        *
        *  IMPORTANT:
        *   for  historical reasons subroutine accepts its parameters in  reversed
        *   order: CorrC1D(Signal, Pattern) = Pattern x Signal (using  traditional
        *   definition of cross-correlation, denoting cross-correlation as "x").
        *
        *  INPUT PARAMETERS
        *   Signal  -   array[0..N-1] - complex function to be transformed,
        *               signal containing pattern
        *   N       -   problem size
        *   Pattern -   array[0..M-1] - complex function to be transformed,
        *               pattern to search withing signal
        *   M       -   problem size
        *
        *  OUTPUT PARAMETERS
        *   R       -   cross-correlation, array[0..N+M-2]:
        * positive lags are stored in R[0..N-1],
        *                 R[i] = sum(conj(pattern[j])*signal[i+j]
        * negative lags are stored in R[N..N+M-2],
        *                 R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j]
        *
        *  NOTE:
        *   It is assumed that pattern domain is [0..M-1].  If Pattern is non-zero
        *  on [-K..M-1],  you can still use this subroutine, just shift result by K.
        *
        *  -- ALGLIB --
        *    Copyright 21.07.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void corrc1d(ref AP.Complex[] signal,
                                   int n,
                                   ref AP.Complex[] pattern,
                                   int m,
                                   ref AP.Complex[] r)
        {
            AP.Complex[] p   = new AP.Complex[0];
            AP.Complex[] b   = new AP.Complex[0];
            int          i   = 0;
            int          i_  = 0;
            int          i1_ = 0;

            System.Diagnostics.Debug.Assert(n > 0 & m > 0, "CorrC1D: incorrect N or M!");
            p = new AP.Complex[m];
            for (i = 0; i <= m - 1; i++)
            {
                p[m - 1 - i] = AP.Math.Conj(pattern[i]);
            }
            conv.convc1d(ref p, m, ref signal, n, ref b);
            r   = new AP.Complex[m + n - 1];
            i1_ = (m - 1) - (0);
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                r[i_] = b[i_ + i1_];
            }
            if (m + n - 2 >= n)
            {
                i1_ = (0) - (n);
                for (i_ = n; i_ <= m + n - 2; i_++)
                {
                    r[i_] = b[i_ + i1_];
                }
            }
        }
        /*************************************************************************
        *  Reference implementation
        *************************************************************************/
        private static void refconvc1d(ref AP.Complex[] a,
                                       int m,
                                       ref AP.Complex[] b,
                                       int n,
                                       ref AP.Complex[] r)
        {
            int i = 0;

            AP.Complex v   = 0;
            int        i_  = 0;
            int        i1_ = 0;

            r = new AP.Complex[m + n - 1];
            for (i = 0; i <= m + n - 2; i++)
            {
                r[i] = 0;
            }
            for (i = 0; i <= m - 1; i++)
            {
                v   = a[i];
                i1_ = (0) - (i);
                for (i_ = i; i_ <= i + n - 1; i_++)
                {
                    r[i_] = r[i_] + v * b[i_ + i1_];
                }
            }
        }
예제 #3
0
        /*************************************************************************
        1-dimensional complex cross-correlation.

        For given Pattern/Signal returns corr(Pattern,Signal) (non-circular).

        Correlation is calculated using reduction to  convolution.  Algorithm with
        max(N,N)*log(max(N,N)) complexity is used (see  ConvC1D()  for  more  info
        about performance).

        IMPORTANT:
            for  historical reasons subroutine accepts its parameters in  reversed
            order: CorrC1D(Signal, Pattern) = Pattern x Signal (using  traditional
            definition of cross-correlation, denoting cross-correlation as "x").

        INPUT PARAMETERS
            Signal  -   array[0..N-1] - complex function to be transformed,
                        signal containing pattern
            N       -   problem size
            Pattern -   array[0..M-1] - complex function to be transformed,
                        pattern to search withing signal
            M       -   problem size

        OUTPUT PARAMETERS
            R       -   cross-correlation, array[0..N+M-2]:
                        * positive lags are stored in R[0..N-1],
                          R[i] = sum(conj(pattern[j])*signal[i+j]
                        * negative lags are stored in R[N..N+M-2],
                          R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j]

        NOTE:
            It is assumed that pattern domain is [0..M-1].  If Pattern is non-zero
        on [-K..M-1],  you can still use this subroutine, just shift result by K.

          -- ALGLIB --
             Copyright 21.07.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void corrc1d(ref AP.Complex[] signal,
            int n,
            ref AP.Complex[] pattern,
            int m,
            ref AP.Complex[] r)
        {
            AP.Complex[] p = new AP.Complex[0];
            AP.Complex[] b = new AP.Complex[0];
            int i = 0;
            int i_ = 0;
            int i1_ = 0;

            System.Diagnostics.Debug.Assert(n>0 & m>0, "CorrC1D: incorrect N or M!");
            p = new AP.Complex[m];
            for(i=0; i<=m-1; i++)
            {
                p[m-1-i] = AP.Math.Conj(pattern[i]);
            }
            conv.convc1d(ref p, m, ref signal, n, ref b);
            r = new AP.Complex[m+n-1];
            i1_ = (m-1) - (0);
            for(i_=0; i_<=n-1;i_++)
            {
                r[i_] = b[i_+i1_];
            }
            if( m+n-2>=n )
            {
                i1_ = (0) - (n);
                for(i_=n; i_<=m+n-2;i_++)
                {
                    r[i_] = b[i_+i1_];
                }
            }
        }
예제 #4
0
        /*************************************************************************
        1-dimensional Fast Hartley Transform.

        Algorithm has O(N*logN) complexity for any N (composite or prime).

        INPUT PARAMETERS
            A   -   array[0..N-1] - real function to be transformed
            N   -   problem size
            
        OUTPUT PARAMETERS
            A   -   FHT of a input array, array[0..N-1],
                    A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1)


          -- ALGLIB --
             Copyright 04.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fhtr1d(ref double[] a,
            int n)
        {
            ftbase.ftplan plan = new ftbase.ftplan();
            int i = 0;
            AP.Complex[] fa = new AP.Complex[0];

            System.Diagnostics.Debug.Assert(n>0, "FHTR1D: incorrect N!");
            
            //
            // Special case: N=1, FHT is just identity transform.
            // After this block we assume that N is strictly greater than 1.
            //
            if( n==1 )
            {
                return;
            }
            
            //
            // Reduce FHt to real FFT
            //
            fft.fftr1d(ref a, n, ref fa);
            for(i=0; i<=n-1; i++)
            {
                a[i] = fa[i].x-fa[i].y;
            }
        }
예제 #5
0
        /*************************************************************************
        *  1-dimensional Fast Hartley Transform.
        *
        *  Algorithm has O(N*logN) complexity for any N (composite or prime).
        *
        *  INPUT PARAMETERS
        *   A   -   array[0..N-1] - real function to be transformed
        *   N   -   problem size
        *
        *  OUTPUT PARAMETERS
        *   A   -   FHT of a input array, array[0..N-1],
        *           A_out[k] = sum(A_in[j]*(cos(2*pi*j*k/N)+sin(2*pi*j*k/N)), j=0..N-1)
        *
        *
        *  -- ALGLIB --
        *    Copyright 04.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fhtr1d(ref double[] a,
                                  int n)
        {
            ftbase.ftplan plan = new ftbase.ftplan();
            int           i    = 0;

            AP.Complex[] fa = new AP.Complex[0];

            System.Diagnostics.Debug.Assert(n > 0, "FHTR1D: incorrect N!");

            //
            // Special case: N=1, FHT is just identity transform.
            // After this block we assume that N is strictly greater than 1.
            //
            if (n == 1)
            {
                return;
            }

            //
            // Reduce FHt to real FFT
            //
            fft.fftr1d(ref a, n, ref fa);
            for (i = 0; i <= n - 1; i++)
            {
                a[i] = fa[i].x - fa[i].y;
            }
        }
        /*************************************************************************
        *  Reference implementation
        *************************************************************************/
        private static void refconvc1dcircular(ref AP.Complex[] a,
                                               int m,
                                               ref AP.Complex[] b,
                                               int n,
                                               ref AP.Complex[] r)
        {
            int i1 = 0;
            int i2 = 0;
            int j2 = 0;

            AP.Complex[] buf = new AP.Complex[0];
            int          i_  = 0;
            int          i1_ = 0;

            refconvc1d(ref a, m, ref b, n, ref buf);
            r = new AP.Complex[m];
            for (i_ = 0; i_ <= m - 1; i_++)
            {
                r[i_] = buf[i_];
            }
            i1 = m;
            while (i1 <= m + n - 2)
            {
                i2  = Math.Min(i1 + m - 1, m + n - 2);
                j2  = i2 - i1;
                i1_ = (i1) - (0);
                for (i_ = 0; i_ <= j2; i_++)
                {
                    r[i_] = r[i_] + buf[i_ + i1_];
                }
                i1 = i1 + m;
            }
        }
예제 #7
0
        /*************************************************************************
        *  Internal subroutine. Never call it directly!
        *
        *
        *  -- ALGLIB --
        *    Copyright 01.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fftr1dinternaleven(ref double[] a,
                                              int n,
                                              ref double[] buf,
                                              ref ftbase.ftplan plan)
        {
            double x   = 0;
            double y   = 0;
            int    i   = 0;
            int    n2  = 0;
            int    idx = 0;

            AP.Complex hn   = 0;
            AP.Complex hmnc = 0;
            AP.Complex v    = 0;
            int        i_   = 0;

            System.Diagnostics.Debug.Assert(n > 0 & n % 2 == 0, "FFTR1DEvenInplace: incorrect N!");

            //
            // Special cases:
            // * N=2
            //
            // After this block we assume that N is strictly greater than 2
            //
            if (n == 2)
            {
                x    = a[0] + a[1];
                y    = a[0] - a[1];
                a[0] = x;
                a[1] = y;
                return;
            }

            //
            // even-size real FFT, use reduction to the complex task
            //
            n2 = n / 2;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                buf[i_] = a[i_];
            }
            ftbase.ftbaseexecuteplan(ref buf, 0, n2, ref plan);
            a[0] = buf[0] + buf[1];
            for (i = 1; i <= n2 - 1; i++)
            {
                idx          = 2 * (i % n2);
                hn.x         = buf[idx + 0];
                hn.y         = buf[idx + 1];
                idx          = 2 * (n2 - i);
                hmnc.x       = buf[idx + 0];
                hmnc.y       = -buf[idx + 1];
                v.x          = -Math.Sin(-(2 * Math.PI * i / n));
                v.y          = Math.Cos(-(2 * Math.PI * i / n));
                v            = hn + hmnc - v * (hn - hmnc);
                a[2 * i + 0] = 0.5 * v.x;
                a[2 * i + 1] = 0.5 * v.y;
            }
            a[1] = buf[0] - buf[1];
        }
예제 #8
0
        /*************************************************************************
        *  Application of an elementary reflection to a rectangular matrix of size MxN
        *
        *  The  algorithm  post-multiplies  the  matrix  by  an elementary reflection
        *  transformation  which  is  given  by  column  V  and  scalar  Tau (see the
        *  description  of  the  GenerateReflection). Not the whole matrix but only a
        *  part  of  it  is  transformed (rows from M1 to M2, columns from N1 to N2).
        *  Only the elements of this submatrix are changed.
        *
        *  Input parameters:
        *   C       -   matrix to be transformed.
        *   Tau     -   scalar defining transformation.
        *   V       -   column defining transformation.
        *               Array whose index ranges within [1..N2-N1+1]
        *   M1, M2  -   range of rows to be transformed.
        *   N1, N2  -   range of columns to be transformed.
        *   WORK    -   working array whose index goes from M1 to M2.
        *
        *  Output parameters:
        *   C       -   the result of multiplying the input matrix C by the
        *               transformation matrix which is given by Tau and V.
        *               If N1>N2 or M1>M2, C is not modified.
        *
        *  -- LAPACK auxiliary 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 complexapplyreflectionfromtheright(ref AP.Complex[,] c,
                                                              AP.Complex tau,
                                                              ref AP.Complex[] v,
                                                              int m1,
                                                              int m2,
                                                              int n1,
                                                              int n2,
                                                              ref AP.Complex[] work)
        {
            AP.Complex t   = 0;
            int        i   = 0;
            int        vm  = 0;
            int        i_  = 0;
            int        i1_ = 0;

            if (tau == 0 | n1 > n2 | m1 > m2)
            {
                return;
            }

            //
            // w := C * v
            //
            vm = n2 - n1 + 1;
            for (i = m1; i <= m2; i++)
            {
                i1_ = (1) - (n1);
                t   = 0.0;
                for (i_ = n1; i_ <= n2; i_++)
                {
                    t += c[i, i_] * v[i_ + i1_];
                }
                work[i] = t;
            }

            //
            // C := C - w * conj(v^T)
            //
            for (i_ = 1; i_ <= vm; i_++)
            {
                v[i_] = AP.Math.Conj(v[i_]);
            }
            for (i = m1; i <= m2; i++)
            {
                t   = work[i] * tau;
                i1_ = (1) - (n1);
                for (i_ = n1; i_ <= n2; i_++)
                {
                    c[i, i_] = c[i, i_] - t * v[i_ + i1_];
                }
            }
            for (i_ = 1; i_ <= vm; i_++)
            {
                v[i_] = AP.Math.Conj(v[i_]);
            }
        }
예제 #9
0
        /*************************************************************************
        *  Generation of random NxN Hermitian positive definite matrix with given
        *  condition number and norm2(A)=1
        *
        *  INPUT PARAMETERS:
        *   N   -   matrix size
        *   C   -   condition number (in 2-norm)
        *
        *  OUTPUT PARAMETERS:
        *   A   -   random HPD matrix with norm2(A)=1 and cond(A)=C
        *
        *  -- ALGLIB routine --
        *    04.12.2009
        *    Bochkanov Sergey
        *************************************************************************/
        public static void hpdmatrixrndcond(int n,
                                            double c,
                                            ref AP.Complex[,] a)
        {
            int    i  = 0;
            int    j  = 0;
            double l1 = 0;
            double l2 = 0;


            //
            // Special cases
            //
            if (n <= 0 | (double)(c) < (double)(1))
            {
                return;
            }
            a = new AP.Complex[n - 1 + 1, n - 1 + 1];
            if (n == 1)
            {
                a[0, 0] = 1;
                return;
            }

            //
            // Prepare matrix
            //
            l1 = 0;
            l2 = Math.Log(1 / c);
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    a[i, j] = 0;
                }
            }
            a[0, 0] = Math.Exp(l1);
            for (i = 1; i <= n - 2; i++)
            {
                a[i, i] = Math.Exp(AP.Math.RandomReal() * (l2 - l1) + l1);
            }
            a[n - 1, n - 1] = Math.Exp(l2);

            //
            // Multiply
            //
            hmatrixrndmultiply(ref a, n);

            //
            // post-process to ensure that matrix diagonal is real
            //
            for (i = 0; i <= n - 1; i++)
            {
                a[i, i].y = 0;
            }
        }
예제 #10
0
        /*************************************************************************
        *  Calculation of the determinant of a general matrix
        *
        *  Input parameters:
        *   A       -   matrix, array[0..N-1, 0..N-1]
        *   N       -   size of matrix A.
        *
        *  Result: determinant of matrix A.
        *
        *  -- ALGLIB --
        *    Copyright 2005 by Bochkanov Sergey
        *************************************************************************/
        public static AP.Complex cmatrixdet(AP.Complex[,] a,
                                            int n)
        {
            AP.Complex result = 0;
            int[]      pivots = new int[0];

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

            trfac.cmatrixlu(ref a, n, n, ref pivots);
            result = cmatrixludet(ref a, ref pivots, n);
            return(result);
        }
예제 #11
0
        /*************************************************************************
        *  Generation of random NxN Hermitian matrix with given condition number  and
        *  norm2(A)=1
        *
        *  INPUT PARAMETERS:
        *   N   -   matrix size
        *   C   -   condition number (in 2-norm)
        *
        *  OUTPUT PARAMETERS:
        *   A   -   random matrix with norm2(A)=1 and cond(A)=C
        *
        *  -- ALGLIB routine --
        *    04.12.2009
        *    Bochkanov Sergey
        *************************************************************************/
        public static void hmatrixrndcond(int n,
                                          double c,
                                          ref AP.Complex[,] a)
        {
            int    i  = 0;
            int    j  = 0;
            double l1 = 0;
            double l2 = 0;

            System.Diagnostics.Debug.Assert(n >= 1 & (double)(c) >= (double)(1), "HMatrixRndCond: N<1 or C<1!");
            a = new AP.Complex[n - 1 + 1, n - 1 + 1];
            if (n == 1)
            {
                //
                // special case
                //
                a[0, 0] = 2 * AP.Math.RandomInteger(2) - 1;
                return;
            }

            //
            // Prepare matrix
            //
            l1 = 0;
            l2 = Math.Log(1 / c);
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    a[i, j] = 0;
                }
            }
            a[0, 0] = Math.Exp(l1);
            for (i = 1; i <= n - 2; i++)
            {
                a[i, i] = (2 * AP.Math.RandomInteger(2) - 1) * Math.Exp(AP.Math.RandomReal() * (l2 - l1) + l1);
            }
            a[n - 1, n - 1] = Math.Exp(l2);

            //
            // Multiply
            //
            hmatrixrndmultiply(ref a, n);

            //
            // post-process to ensure that matrix diagonal is real
            //
            for (i = 0; i <= n - 1; i++)
            {
                a[i, i].y = 0;
            }
        }
예제 #12
0
        /*************************************************************************
        *  1-dimensional real inverse FFT.
        *
        *  Algorithm has O(N*logN) complexity for any N (composite or prime).
        *
        *  INPUT PARAMETERS
        *   F   -   array[0..floor(N/2)] - frequencies from forward real FFT
        *   N   -   problem size
        *
        *  OUTPUT PARAMETERS
        *   A   -   inverse DFT of a input array, array[0..N-1]
        *
        *  NOTE:
        *   F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just  one
        *  half of frequencies array is needed - elements from 0 to floor(N/2).  F[0]
        *  is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd,  then
        *  F[floor(N/2)] has no special properties.
        *
        *  Relying on properties noted above, FFTR1DInv subroutine uses only elements
        *  from 0th to floor(N/2)-th. It ignores imaginary part of F[0],  and in case
        *  N is even it ignores imaginary part of F[floor(N/2)] too.  So you can pass
        *  either frequencies array with N elements or reduced array with roughly N/2
        *  elements - subroutine will successfully transform both.
        *
        *
        *  -- ALGLIB --
        *    Copyright 01.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fftr1dinv(ref AP.Complex[] f,
                                     int n,
                                     ref double[] a)
        {
            int i = 0;

            double[]     h  = new double[0];
            AP.Complex[] fh = new AP.Complex[0];

            System.Diagnostics.Debug.Assert(n > 0, "FFTR1DInv: incorrect N!");

            //
            // Special case: N=1, FFT is just identity transform.
            // After this block we assume that N is strictly greater than 1.
            //
            if (n == 1)
            {
                a    = new double[1];
                a[0] = f[0].x;
                return;
            }

            //
            // inverse real FFT is reduced to the inverse real FHT,
            // which is reduced to the forward real FHT,
            // which is reduced to the forward real FFT.
            //
            // Don't worry, it is really compact and efficient reduction :)
            //
            h    = new double[n];
            a    = new double[n];
            h[0] = f[0].x;
            for (i = 1; i <= (int)Math.Floor((double)(n) / (double)(2)) - 1; i++)
            {
                h[i]     = f[i].x - f[i].y;
                h[n - i] = f[i].x + f[i].y;
            }
            if (n % 2 == 0)
            {
                h[(int)Math.Floor((double)(n) / (double)(2))] = f[(int)Math.Floor((double)(n) / (double)(2))].x;
            }
            else
            {
                h[(int)Math.Floor((double)(n) / (double)(2))]     = f[(int)Math.Floor((double)(n) / (double)(2))].x - f[(int)Math.Floor((double)(n) / (double)(2))].y;
                h[(int)Math.Floor((double)(n) / (double)(2)) + 1] = f[(int)Math.Floor((double)(n) / (double)(2))].x + f[(int)Math.Floor((double)(n) / (double)(2))].y;
            }
            fftr1d(ref h, n, ref fh);
            for (i = 0; i <= n - 1; i++)
            {
                a[i] = (fh[i].x - fh[i].y) / n;
            }
        }
예제 #13
0
        /*************************************************************************
        *  Application of an elementary reflection to a rectangular matrix of size MxN
        *
        *  The  algorithm  pre-multiplies  the  matrix  by  an  elementary reflection
        *  transformation  which  is  given  by  column  V  and  scalar  Tau (see the
        *  description of the GenerateReflection). Not the whole matrix  but  only  a
        *  part of it is transformed (rows from M1 to M2, columns from N1 to N2). Only
        *  the elements of this submatrix are changed.
        *
        *  Note: the matrix is multiplied by H, not by H'.   If  it  is  required  to
        *  multiply the matrix by H', it is necessary to pass Conj(Tau) instead of Tau.
        *
        *  Input parameters:
        *   C       -   matrix to be transformed.
        *   Tau     -   scalar defining transformation.
        *   V       -   column defining transformation.
        *               Array whose index ranges within [1..M2-M1+1]
        *   M1, M2  -   range of rows to be transformed.
        *   N1, N2  -   range of columns to be transformed.
        *   WORK    -   working array whose index goes from N1 to N2.
        *
        *  Output parameters:
        *   C       -   the result of multiplying the input matrix C by the
        *               transformation matrix which is given by Tau and V.
        *               If N1>N2 or M1>M2, C is not modified.
        *
        *  -- LAPACK auxiliary 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 complexapplyreflectionfromtheleft(ref AP.Complex[,] c,
                                                             AP.Complex tau,
                                                             ref AP.Complex[] v,
                                                             int m1,
                                                             int m2,
                                                             int n1,
                                                             int n2,
                                                             ref AP.Complex[] work)
        {
            AP.Complex t  = 0;
            int        i  = 0;
            int        vm = 0;
            int        i_ = 0;

            if (tau == 0 | n1 > n2 | m1 > m2)
            {
                return;
            }

            //
            // w := C^T * conj(v)
            //
            vm = m2 - m1 + 1;
            for (i = n1; i <= n2; i++)
            {
                work[i] = 0;
            }
            for (i = m1; i <= m2; i++)
            {
                t = AP.Math.Conj(v[i + 1 - m1]);
                for (i_ = n1; i_ <= n2; i_++)
                {
                    work[i_] = work[i_] + t * c[i, i_];
                }
            }

            //
            // C := C - tau * v * w^T
            //
            for (i = m1; i <= m2; i++)
            {
                t = v[i - m1 + 1] * tau;
                for (i_ = n1; i_ <= n2; i_++)
                {
                    c[i, i_] = c[i, i_] - t * work[i_];
                }
            }
        }
예제 #14
0
        /*************************************************************************
        *  complex basic solver-updater for reduced linear system
        *
        *   alpha*x[i] = beta
        *
        *  solves this equation and updates it in overlfow-safe manner (keeping track
        *  of relative growth of solution).
        *
        *  Parameters:
        *   Alpha   -   alpha
        *   Beta    -   beta
        *   LnMax   -   precomputed Ln(MaxRealNumber)
        *   BNorm   -   inf-norm of b (right part of original system)
        *   MaxGrowth-  maximum growth of norm(x) relative to norm(b)
        *   XNorm   -   inf-norm of other components of X (which are already processed)
        *               it is updated by CBasicSolveAndUpdate.
        *   X       -   solution
        *
        *  -- ALGLIB routine --
        *    26.01.2009
        *    Bochkanov Sergey
        *************************************************************************/
        private static bool cbasicsolveandupdate(AP.Complex alpha,
                                                 AP.Complex beta,
                                                 double lnmax,
                                                 double bnorm,
                                                 double maxgrowth,
                                                 ref double xnorm,
                                                 ref AP.Complex x)
        {
            bool   result = new bool();
            double v      = 0;

            result = false;
            if (alpha == 0)
            {
                return(result);
            }
            if (beta != 0)
            {
                //
                // alpha*x[i]=beta
                //
                v = Math.Log(AP.Math.AbsComplex(beta)) - Math.Log(AP.Math.AbsComplex(alpha));
                if ((double)(v) > (double)(lnmax))
                {
                    return(result);
                }
                x = beta / alpha;
            }
            else
            {
                //
                // alpha*x[i]=0
                //
                x = 0;
            }

            //
            // update NrmX, test growth limit
            //
            xnorm = Math.Max(xnorm, AP.Math.AbsComplex(x));
            if ((double)(xnorm) > (double)(maxgrowth * bnorm))
            {
                return(result);
            }
            result = true;
            return(result);
        }
예제 #15
0
        /*************************************************************************
        *  Copy
        *************************************************************************/
        private static void cmatrixmakeacopy(ref AP.Complex[,] a,
                                             int m,
                                             int n,
                                             ref AP.Complex[,] b)
        {
            int i = 0;
            int j = 0;

            b = new AP.Complex[m - 1 + 1, n - 1 + 1];
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    b[i, j] = a[i, j];
                }
            }
        }
예제 #16
0
        /*************************************************************************
        *  Reference implementation
        *************************************************************************/
        private static void refcorrc1d(ref AP.Complex[] signal,
                                       int n,
                                       ref AP.Complex[] pattern,
                                       int m,
                                       ref AP.Complex[] r)
        {
            int i = 0;
            int j = 0;

            AP.Complex   v  = 0;
            AP.Complex[] s  = new AP.Complex[0];
            int          i_ = 0;

            s = new AP.Complex[m + n - 1];
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                s[i_] = signal[i_];
            }
            for (i = n; i <= m + n - 2; i++)
            {
                s[i] = 0;
            }
            r = new AP.Complex[m + n - 1];
            for (i = 0; i <= n - 1; i++)
            {
                v = 0;
                for (j = 0; j <= m - 1; j++)
                {
                    if (i + j >= n)
                    {
                        break;
                    }
                    v = v + AP.Math.Conj(pattern[j]) * s[i + j];
                }
                r[i] = v;
            }
            for (i = 1; i <= m - 1; i++)
            {
                v = 0;
                for (j = i; j <= m - 1; j++)
                {
                    v = v + AP.Math.Conj(pattern[j]) * s[j - i];
                }
                r[m + n - 1 - i] = v;
            }
        }
예제 #17
0
        /*************************************************************************
        *  Generation of random NxN complex matrix with given condition number C and
        *  norm2(A)=1
        *
        *  INPUT PARAMETERS:
        *   N   -   matrix size
        *   C   -   condition number (in 2-norm)
        *
        *  OUTPUT PARAMETERS:
        *   A   -   random matrix with norm2(A)=1 and cond(A)=C
        *
        *  -- ALGLIB routine --
        *    04.12.2009
        *    Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixrndcond(int n,
                                          double c,
                                          ref AP.Complex[,] a)
        {
            int    i  = 0;
            int    j  = 0;
            double l1 = 0;
            double l2 = 0;

            hqrnd.hqrndstate state = new hqrnd.hqrndstate();
            AP.Complex       v     = 0;

            System.Diagnostics.Debug.Assert(n >= 1 & (double)(c) >= (double)(1), "CMatrixRndCond: N<1 or C<1!");
            a = new AP.Complex[n - 1 + 1, n - 1 + 1];
            if (n == 1)
            {
                //
                // special case
                //
                hqrnd.hqrndrandomize(ref state);
                hqrnd.hqrndunit2(ref state, ref v.x, ref v.y);
                a[0, 0] = v;
                return;
            }
            l1 = 0;
            l2 = Math.Log(1 / c);
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    a[i, j] = 0;
                }
            }
            a[0, 0] = Math.Exp(l1);
            for (i = 1; i <= n - 2; i++)
            {
                a[i, i] = Math.Exp(AP.Math.RandomReal() * (l2 - l1) + l1);
            }
            a[n - 1, n - 1] = Math.Exp(l2);
            cmatrixrndorthogonalfromtheleft(ref a, n, n);
            cmatrixrndorthogonalfromtheright(ref a, n, n);
        }
예제 #18
0
        /*************************************************************************
        *  Internal real FFT stub.
        *  Uses straightforward formula with O(N^2) complexity.
        *************************************************************************/
        private static void refinternalrfft(ref double[] a,
                                            int nn,
                                            ref AP.Complex[] f)
        {
            double[] tmp = new double[0];
            int      i   = 0;

            tmp = new double[2 * nn - 1 + 1];
            for (i = 0; i <= nn - 1; i++)
            {
                tmp[2 * i]     = a[i];
                tmp[2 * i + 1] = 0;
            }
            refinternalcfft(ref tmp, nn, false);
            f = new AP.Complex[nn];
            for (i = 0; i <= nn - 1; i++)
            {
                f[i].x = tmp[2 * i + 0];
                f[i].y = tmp[2 * i + 1];
            }
        }
예제 #19
0
        /*************************************************************************
        *  Determinant calculation of the matrix given by its LU decomposition.
        *
        *  Input parameters:
        *   A       -   LU decomposition of the matrix (output of
        *               RMatrixLU subroutine).
        *   Pivots  -   table of permutations which were made during
        *               the LU decomposition.
        *               Output of RMatrixLU subroutine.
        *   N       -   size of matrix A.
        *
        *  Result: matrix determinant.
        *
        *  -- ALGLIB --
        *    Copyright 2005 by Bochkanov Sergey
        *************************************************************************/
        public static AP.Complex cmatrixludet(ref AP.Complex[,] a,
                                              ref int[] pivots,
                                              int n)
        {
            AP.Complex result = 0;
            int        i      = 0;
            int        s      = 0;

            result = 1;
            s      = 1;
            for (i = 0; i <= n - 1; i++)
            {
                result = result * a[i, i];
                if (pivots[i] != i)
                {
                    s = -s;
                }
            }
            result = result * s;
            return(result);
        }
예제 #20
0
        /*************************************************************************
        *  Fast kernel
        *
        *  -- ALGLIB routine --
        *    19.01.2010
        *    Bochkanov Sergey
        *************************************************************************/
        public static bool cmatrixgemmf(int m,
                                        int n,
                                        int k,
                                        AP.Complex alpha,
                                        ref AP.Complex[,] a,
                                        int ia,
                                        int ja,
                                        int optypea,
                                        ref AP.Complex[,] b,
                                        int ib,
                                        int jb,
                                        int optypeb,
                                        AP.Complex beta,
                                        ref AP.Complex[,] c,
                                        int ic,
                                        int jc)
        {
            bool result = new bool();

            result = false;
            return(result);
        }
예제 #21
0
        /*************************************************************************
        *  Reference implementation
        *************************************************************************/
        private static void refcorrc1dcircular(ref AP.Complex[] signal,
                                               int n,
                                               ref AP.Complex[] pattern,
                                               int m,
                                               ref AP.Complex[] r)
        {
            int i = 0;
            int j = 0;

            AP.Complex v = 0;

            r = new AP.Complex[n];
            for (i = 0; i <= n - 1; i++)
            {
                v = 0;
                for (j = 0; j <= m - 1; j++)
                {
                    v = v + AP.Math.Conj(pattern[j]) * signal[(i + j) % n];
                }
                r[i] = v;
            }
        }
예제 #22
0
        /*************************************************************************
        *  Generation of a random Haar distributed orthogonal complex matrix
        *
        *  INPUT PARAMETERS:
        *   N   -   matrix size, N>=1
        *
        *  OUTPUT PARAMETERS:
        *   A   -   orthogonal NxN matrix, array[0..N-1,0..N-1]
        *
        *  -- ALGLIB routine --
        *    04.12.2009
        *    Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixrndorthogonal(int n,
                                                ref AP.Complex[,] a)
        {
            int i = 0;
            int j = 0;

            System.Diagnostics.Debug.Assert(n >= 1, "CMatrixRndOrthogonal: N<1!");
            a = new AP.Complex[n - 1 + 1, n - 1 + 1];
            for (i = 0; i <= n - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    if (i == j)
                    {
                        a[i, j] = 1;
                    }
                    else
                    {
                        a[i, j] = 0;
                    }
                }
            }
            cmatrixrndorthogonalfromtheright(ref a, n, n);
        }
예제 #23
0
        private static void testcluproblem(ref AP.Complex[,] a,
                                           int m,
                                           int n,
                                           double threshold,
                                           ref bool err,
                                           ref bool properr)
        {
            AP.Complex[,] ca  = new AP.Complex[0, 0];
            AP.Complex[,] cl  = new AP.Complex[0, 0];
            AP.Complex[,] cu  = new AP.Complex[0, 0];
            AP.Complex[,] ca2 = new AP.Complex[0, 0];
            AP.Complex[] ct    = new AP.Complex[0];
            int          i     = 0;
            int          j     = 0;
            int          minmn = 0;

            AP.Complex v  = 0;
            int[]      p  = new int[0];
            int        i_ = 0;

            minmn = Math.Min(m, n);

            //
            // PLU test
            //
            ca = new AP.Complex[m, n];
            for (i = 0; i <= m - 1; i++)
            {
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    ca[i, i_] = a[i, i_];
                }
            }
            trfac.cmatrixplu(ref ca, m, n, ref p);
            for (i = 0; i <= minmn - 1; i++)
            {
                if (p[i] < i | p[i] >= m)
                {
                    properr = false;
                    return;
                }
            }
            cl = new AP.Complex[m, minmn];
            for (j = 0; j <= minmn - 1; j++)
            {
                for (i = 0; i <= j - 1; i++)
                {
                    cl[i, j] = 0.0;
                }
                cl[j, j] = 1.0;
                for (i = j + 1; i <= m - 1; i++)
                {
                    cl[i, j] = ca[i, j];
                }
            }
            cu = new AP.Complex[minmn, n];
            for (i = 0; i <= minmn - 1; i++)
            {
                for (j = 0; j <= i - 1; j++)
                {
                    cu[i, j] = 0.0;
                }
                for (j = i; j <= n - 1; j++)
                {
                    cu[i, j] = ca[i, j];
                }
            }
            ca2 = new AP.Complex[m, n];
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    v = 0.0;
                    for (i_ = 0; i_ <= minmn - 1; i_++)
                    {
                        v += cl[i, i_] * cu[i_, j];
                    }
                    ca2[i, j] = v;
                }
            }
            ct = new AP.Complex[n];
            for (i = minmn - 1; i >= 0; i--)
            {
                if (i != p[i])
                {
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        ct[i_] = ca2[i, i_];
                    }
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        ca2[i, i_] = ca2[p[i], i_];
                    }
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        ca2[p[i], i_] = ct[i_];
                    }
                }
            }
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    err = err | (double)(AP.Math.AbsComplex(a[i, j] - ca2[i, j])) > (double)(threshold);
                }
            }

            //
            // LUP test
            //
            ca = new AP.Complex[m, n];
            for (i = 0; i <= m - 1; i++)
            {
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    ca[i, i_] = a[i, i_];
                }
            }
            trfac.cmatrixlup(ref ca, m, n, ref p);
            for (i = 0; i <= minmn - 1; i++)
            {
                if (p[i] < i | p[i] >= n)
                {
                    properr = false;
                    return;
                }
            }
            cl = new AP.Complex[m, minmn];
            for (j = 0; j <= minmn - 1; j++)
            {
                for (i = 0; i <= j - 1; i++)
                {
                    cl[i, j] = 0.0;
                }
                for (i = j; i <= m - 1; i++)
                {
                    cl[i, j] = ca[i, j];
                }
            }
            cu = new AP.Complex[minmn, n];
            for (i = 0; i <= minmn - 1; i++)
            {
                for (j = 0; j <= i - 1; j++)
                {
                    cu[i, j] = 0.0;
                }
                cu[i, i] = 1.0;
                for (j = i + 1; j <= n - 1; j++)
                {
                    cu[i, j] = ca[i, j];
                }
            }
            ca2 = new AP.Complex[m, n];
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    v = 0.0;
                    for (i_ = 0; i_ <= minmn - 1; i_++)
                    {
                        v += cl[i, i_] * cu[i_, j];
                    }
                    ca2[i, j] = v;
                }
            }
            ct = new AP.Complex[m];
            for (i = minmn - 1; i >= 0; i--)
            {
                if (i != p[i])
                {
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        ct[i_] = ca2[i_, i];
                    }
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        ca2[i_, i] = ca2[i_, p[i]];
                    }
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        ca2[i_, p[i]] = ct[i_];
                    }
                }
            }
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= n - 1; j++)
                {
                    err = err | (double)(AP.Math.AbsComplex(a[i, j] - ca2[i, j])) > (double)(threshold);
                }
            }
        }
        /*************************************************************************
        Checks whether solver results indicate singular matrix.
        Returns True on success.
        *************************************************************************/
        private static bool cmatrixchecksingular(int n,
            int info,
            ref densesolver.densesolverreport rep,
            ref AP.Complex[] xs)
        {
            bool result = new bool();
            AP.Complex[,] xsm = new AP.Complex[0,0];
            int i_ = 0;

            xsm = new AP.Complex[n, 1];
            for(i_=0; i_<=n-1;i_++)
            {
                xsm[i_,0] = xs[i_];
            }
            result = cmatrixchecksingularm(n, 1, info, ref rep, ref xsm);
            return result;
        }
예제 #25
0
        /*************************************************************************
        Test
        *************************************************************************/
        public static bool testfft(bool silent)
        {
            bool result = new bool();
            int n = 0;
            int i = 0;
            int k = 0;
            AP.Complex[] a1 = new AP.Complex[0];
            AP.Complex[] a2 = new AP.Complex[0];
            AP.Complex[] a3 = new AP.Complex[0];
            double[] r1 = new double[0];
            double[] r2 = new double[0];
            double[] buf = new double[0];
            ftbase.ftplan plan = new ftbase.ftplan();
            int maxn = 0;
            double bidierr = 0;
            double bidirerr = 0;
            double referr = 0;
            double refrerr = 0;
            double reinterr = 0;
            double errtol = 0;
            bool referrors = new bool();
            bool bidierrors = new bool();
            bool refrerrors = new bool();
            bool bidirerrors = new bool();
            bool reinterrors = new bool();
            bool waserrors = new bool();
            int i_ = 0;

            maxn = 128;
            errtol = 100000*Math.Pow(maxn, (double)(3)/(double)(2))*AP.Math.MachineEpsilon;
            bidierrors = false;
            referrors = false;
            bidirerrors = false;
            refrerrors = false;
            reinterrors = false;
            waserrors = false;
            
            //
            // Test bi-directional error: norm(x-invFFT(FFT(x)))
            //
            bidierr = 0;
            bidirerr = 0;
            for(n=1; n<=maxn; n++)
            {
                
                //
                // Complex FFT/invFFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                a3 = new AP.Complex[n];
                for(i=0; i<=n-1; i++)
                {
                    a1[i].x = 2*AP.Math.RandomReal()-1;
                    a1[i].y = 2*AP.Math.RandomReal()-1;
                    a2[i] = a1[i];
                    a3[i] = a1[i];
                }
                fft.fftc1d(ref a2, n);
                fft.fftc1dinv(ref a2, n);
                fft.fftc1dinv(ref a3, n);
                fft.fftc1d(ref a3, n);
                for(i=0; i<=n-1; i++)
                {
                    bidierr = Math.Max(bidierr, AP.Math.AbsComplex(a1[i]-a2[i]));
                    bidierr = Math.Max(bidierr, AP.Math.AbsComplex(a1[i]-a3[i]));
                }
                
                //
                // Real
                //
                r1 = new double[n];
                r2 = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    r1[i] = 2*AP.Math.RandomReal()-1;
                    r2[i] = r1[i];
                }
                fft.fftr1d(ref r2, n, ref a1);
                for(i_=0; i_<=n-1;i_++)
                {
                    r2[i_] = 0*r2[i_];
                }
                fft.fftr1dinv(ref a1, n, ref r2);
                for(i=0; i<=n-1; i++)
                {
                    bidirerr = Math.Max(bidirerr, AP.Math.AbsComplex(r1[i]-r2[i]));
                }
            }
            bidierrors = bidierrors | (double)(bidierr)>(double)(errtol);
            bidirerrors = bidirerrors | (double)(bidirerr)>(double)(errtol);
            
            //
            // Test against reference O(N^2) implementation
            //
            referr = 0;
            refrerr = 0;
            for(n=1; n<=maxn; n++)
            {
                
                //
                // Complex FFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                for(i=0; i<=n-1; i++)
                {
                    a1[i].x = 2*AP.Math.RandomReal()-1;
                    a1[i].y = 2*AP.Math.RandomReal()-1;
                    a2[i] = a1[i];
                }
                fft.fftc1d(ref a1, n);
                reffftc1d(ref a2, n);
                for(i=0; i<=n-1; i++)
                {
                    referr = Math.Max(referr, AP.Math.AbsComplex(a1[i]-a2[i]));
                }
                
                //
                // Complex inverse FFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                for(i=0; i<=n-1; i++)
                {
                    a1[i].x = 2*AP.Math.RandomReal()-1;
                    a1[i].y = 2*AP.Math.RandomReal()-1;
                    a2[i] = a1[i];
                }
                fft.fftc1dinv(ref a1, n);
                reffftc1dinv(ref a2, n);
                for(i=0; i<=n-1; i++)
                {
                    referr = Math.Max(referr, AP.Math.AbsComplex(a1[i]-a2[i]));
                }
                
                //
                // Real forward/inverse FFT:
                // * calculate and check forward FFT
                // * use precalculated FFT to check backward FFT
                //   fill unused parts of frequencies array with random numbers
                //   to ensure that they are not really used
                //
                r1 = new double[n];
                r2 = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    r1[i] = 2*AP.Math.RandomReal()-1;
                    r2[i] = r1[i];
                }
                fft.fftr1d(ref r1, n, ref a1);
                refinternalrfft(ref r2, n, ref a2);
                for(i=0; i<=n-1; i++)
                {
                    refrerr = Math.Max(refrerr, AP.Math.AbsComplex(a1[i]-a2[i]));
                }
                a3 = new AP.Complex[(int)Math.Floor((double)(n)/(double)(2))+1];
                for(i=0; i<=(int)Math.Floor((double)(n)/(double)(2)); i++)
                {
                    a3[i] = a2[i];
                }
                a3[0].y = 2*AP.Math.RandomReal()-1;
                if( n%2==0 )
                {
                    a3[(int)Math.Floor((double)(n)/(double)(2))].y = 2*AP.Math.RandomReal()-1;
                }
                for(i=0; i<=n-1; i++)
                {
                    r1[i] = 0;
                }
                fft.fftr1dinv(ref a3, n, ref r1);
                for(i=0; i<=n-1; i++)
                {
                    refrerr = Math.Max(refrerr, Math.Abs(r2[i]-r1[i]));
                }
            }
            referrors = referrors | (double)(referr)>(double)(errtol);
            refrerrors = refrerrors | (double)(refrerr)>(double)(errtol);
            
            //
            // test internal real even FFT
            //
            reinterr = 0;
            for(k=1; k<=maxn/2; k++)
            {
                n = 2*k;
                
                //
                // Real forward FFT
                //
                r1 = new double[n];
                r2 = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    r1[i] = 2*AP.Math.RandomReal()-1;
                    r2[i] = r1[i];
                }
                ftbase.ftbasegeneratecomplexfftplan(n/2, ref plan);
                buf = new double[n];
                fft.fftr1dinternaleven(ref r1, n, ref buf, ref plan);
                refinternalrfft(ref r2, n, ref a2);
                reinterr = Math.Max(reinterr, Math.Abs(r1[0]-a2[0].x));
                reinterr = Math.Max(reinterr, Math.Abs(r1[1]-a2[n/2].x));
                for(i=1; i<=n/2-1; i++)
                {
                    reinterr = Math.Max(reinterr, Math.Abs(r1[2*i+0]-a2[i].x));
                    reinterr = Math.Max(reinterr, Math.Abs(r1[2*i+1]-a2[i].y));
                }
                
                //
                // Real backward FFT
                //
                r1 = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    r1[i] = 2*AP.Math.RandomReal()-1;
                }
                a2 = new AP.Complex[(int)Math.Floor((double)(n)/(double)(2))+1];
                a2[0] = r1[0];
                for(i=1; i<=(int)Math.Floor((double)(n)/(double)(2))-1; i++)
                {
                    a2[i].x = r1[2*i+0];
                    a2[i].y = r1[2*i+1];
                }
                a2[(int)Math.Floor((double)(n)/(double)(2))] = r1[1];
                ftbase.ftbasegeneratecomplexfftplan(n/2, ref plan);
                buf = new double[n];
                fft.fftr1dinvinternaleven(ref r1, n, ref buf, ref plan);
                fft.fftr1dinv(ref a2, n, ref r2);
                for(i=0; i<=n-1; i++)
                {
                    reinterr = Math.Max(reinterr, Math.Abs(r1[i]-r2[i]));
                }
            }
            reinterrors = reinterrors | (double)(reinterr)>(double)(errtol);
            
            //
            // end
            //
            waserrors = bidierrors | bidirerrors | referrors | refrerrors | reinterrors;
            if( !silent )
            {
                System.Console.Write("TESTING FFT");
                System.Console.WriteLine();
                System.Console.Write("FINAL RESULT:                             ");
                if( waserrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* BI-DIRECTIONAL COMPLEX TEST:            ");
                if( bidierrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE COMPLEX FFT:          ");
                if( referrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* BI-DIRECTIONAL REAL TEST:               ");
                if( bidirerrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE REAL FFT:             ");
                if( refrerrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* INTERNAL EVEN FFT:                      ");
                if( reinterrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                if( waserrors )
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
            }
            result = !waserrors;
            return result;
        }
        /*************************************************************************
        HPD test
        *************************************************************************/
        private static void testhpdsolver(int maxn,
            int maxm,
            int passcount,
            double threshold,
            ref bool hpderrors,
            ref bool rfserrors)
        {
            AP.Complex[,] a = new AP.Complex[0,0];
            AP.Complex[,] cha = new AP.Complex[0,0];
            AP.Complex[,] atmp = new AP.Complex[0,0];
            int[] p = new int[0];
            AP.Complex[,] xe = new AP.Complex[0,0];
            AP.Complex[,] b = new AP.Complex[0,0];
            AP.Complex[] bv = new AP.Complex[0];
            int i = 0;
            int j = 0;
            int k = 0;
            int n = 0;
            int m = 0;
            int pass = 0;
            int taskkind = 0;
            double mx = 0;
            AP.Complex v = 0;
            bool isupper = new bool();
            int info = 0;
            densesolver.densesolverreport rep = new densesolver.densesolverreport();
            densesolver.densesolverlsreport repls = new densesolver.densesolverlsreport();
            AP.Complex[,] x = new AP.Complex[0,0];
            AP.Complex[] xv = new AP.Complex[0];
            AP.Complex[] y = new AP.Complex[0];
            AP.Complex[] tx = new AP.Complex[0];
            int i_ = 0;

            
            //
            // General square matrices:
            // * test general solvers
            // * test least squares solver
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    for(m=1; m<=maxm; m++)
                    {
                        
                        //
                        // ********************************************************
                        // WELL CONDITIONED TASKS
                        // ability to find correct solution is tested
                        // ********************************************************
                        //
                        // 1. generate random well conditioned matrix A.
                        // 2. generate random solution vector xe
                        // 3. generate right part b=A*xe
                        // 4. test different methods on original A
                        //
                        isupper = (double)(AP.Math.RandomReal())>(double)(0.5);
                        matgen.hpdmatrixrndcond(n, 1000, ref a);
                        cmatrixmakeacopy(ref a, n, n, ref cha);
                        if( !trfac.hpdmatrixcholesky(ref cha, n, isupper) )
                        {
                            hpderrors = true;
                            return;
                        }
                        xe = new AP.Complex[n, m];
                        for(i=0; i<=n-1; i++)
                        {
                            for(j=0; j<=m-1; j++)
                            {
                                xe[i,j].x = 2*AP.Math.RandomReal()-1;
                                xe[i,j].y = 2*AP.Math.RandomReal()-1;
                            }
                        }
                        b = new AP.Complex[n, m];
                        for(i=0; i<=n-1; i++)
                        {
                            for(j=0; j<=m-1; j++)
                            {
                                v = 0.0;
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    v += a[i,i_]*xe[i_,j];
                                }
                                b[i,j] = v;
                            }
                        }
                        cmatrixdrophalf(ref a, n, isupper);
                        cmatrixdrophalf(ref cha, n, isupper);
                        
                        //
                        // Test solvers
                        //
                        info = 0;
                        unsetrep(ref rep);
                        cunset2d(ref x);
                        densesolver.hpdmatrixsolvem(ref a, n, isupper, ref b, m, ref info, ref rep, ref x);
                        hpderrors = hpderrors | !cmatrixchecksolutionm(ref xe, n, m, threshold, info, ref rep, ref x);
                        info = 0;
                        unsetrep(ref rep);
                        cunset1d(ref xv);
                        bv = new AP.Complex[n];
                        for(i_=0; i_<=n-1;i_++)
                        {
                            bv[i_] = b[i_,0];
                        }
                        densesolver.hpdmatrixsolve(ref a, n, isupper, ref bv, ref info, ref rep, ref xv);
                        hpderrors = hpderrors | !cmatrixchecksolution(ref xe, n, threshold, info, ref rep, ref xv);
                        info = 0;
                        unsetrep(ref rep);
                        cunset2d(ref x);
                        densesolver.hpdmatrixcholeskysolvem(ref cha, n, isupper, ref b, m, ref info, ref rep, ref x);
                        hpderrors = hpderrors | !cmatrixchecksolutionm(ref xe, n, m, threshold, info, ref rep, ref x);
                        info = 0;
                        unsetrep(ref rep);
                        cunset1d(ref xv);
                        bv = new AP.Complex[n];
                        for(i_=0; i_<=n-1;i_++)
                        {
                            bv[i_] = b[i_,0];
                        }
                        densesolver.hpdmatrixcholeskysolve(ref cha, n, isupper, ref bv, ref info, ref rep, ref xv);
                        hpderrors = hpderrors | !cmatrixchecksolution(ref xe, n, threshold, info, ref rep, ref xv);
                        
                        //
                        // ********************************************************
                        // EXACTLY SINGULAR MATRICES
                        // ability to detect singularity is tested
                        // ********************************************************
                        //
                        // 1. generate different types of singular matrices:
                        //    * zero
                        //    * with zero columns
                        //    * with zero rows
                        //    * with equal rows/columns
                        // 2. generate random solution vector xe
                        // 3. generate right part b=A*xe
                        // 4. test different methods
                        //
                        for(taskkind=0; taskkind<=3; taskkind++)
                        {
                            cunset2d(ref a);
                            if( taskkind==0 )
                            {
                                
                                //
                                // all zeros
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j] = 0;
                                    }
                                }
                            }
                            if( taskkind==1 )
                            {
                                
                                //
                                // there is zero column
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=i; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                        if( i==j )
                                        {
                                            a[i,j].y = 0;
                                        }
                                        a[j,i] = a[i,j];
                                    }
                                }
                                k = AP.Math.RandomInteger(n);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[i_,k] = 0*a[i_,k];
                                }
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[k,i_] = 0*a[k,i_];
                                }
                            }
                            if( taskkind==2 )
                            {
                                
                                //
                                // there is zero row
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=i; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                        if( i==j )
                                        {
                                            a[i,j].y = 0;
                                        }
                                        a[j,i] = a[i,j];
                                    }
                                }
                                k = AP.Math.RandomInteger(n);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[k,i_] = 0*a[k,i_];
                                }
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[i_,k] = 0*a[i_,k];
                                }
                            }
                            if( taskkind==3 )
                            {
                                
                                //
                                // equal columns/rows
                                //
                                if( n<2 )
                                {
                                    continue;
                                }
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=i; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                        if( i==j )
                                        {
                                            a[i,j].y = 0;
                                        }
                                        a[j,i] = a[i,j];
                                    }
                                }
                                k = 1+AP.Math.RandomInteger(n-1);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[i_,0] = a[i_,k];
                                }
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[0,i_] = a[k,i_];
                                }
                            }
                            xe = new AP.Complex[n, m];
                            for(i=0; i<=n-1; i++)
                            {
                                for(j=0; j<=m-1; j++)
                                {
                                    xe[i,j] = 2*AP.Math.RandomReal()-1;
                                }
                            }
                            b = new AP.Complex[n, m];
                            for(i=0; i<=n-1; i++)
                            {
                                for(j=0; j<=m-1; j++)
                                {
                                    v = 0.0;
                                    for(i_=0; i_<=n-1;i_++)
                                    {
                                        v += a[i,i_]*xe[i_,j];
                                    }
                                    b[i,j] = v;
                                }
                            }
                            cmatrixmakeacopy(ref a, n, n, ref cha);
                            cmatrixdrophalf(ref a, n, isupper);
                            cmatrixdrophalf(ref cha, n, isupper);
                            
                            //
                            // Test SPDMatrixSolveM()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            densesolver.hpdmatrixsolvem(ref a, n, isupper, ref b, m, ref info, ref rep, ref x);
                            hpderrors = hpderrors | !cmatrixchecksingularm(n, m, info, ref rep, ref x);
                            
                            //
                            // Test SPDMatrixSolve()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            bv = new AP.Complex[n];
                            for(i_=0; i_<=n-1;i_++)
                            {
                                bv[i_] = b[i_,0];
                            }
                            densesolver.hpdmatrixsolve(ref a, n, isupper, ref bv, ref info, ref rep, ref xv);
                            hpderrors = hpderrors | !cmatrixchecksingular(n, info, ref rep, ref xv);
                            
                            //
                            // 'equal columns/rows' are degenerate, but
                            // Cholesky matrix with equal columns/rows IS NOT degenerate,
                            // so it is not used for testing purposes.
                            //
                            if( taskkind!=3 )
                            {
                                
                                //
                                // Test SPDMatrixLUSolveM()
                                //
                                info = 0;
                                unsetrep(ref rep);
                                cunset2d(ref x);
                                densesolver.hpdmatrixcholeskysolvem(ref cha, n, isupper, ref b, m, ref info, ref rep, ref x);
                                hpderrors = hpderrors | !cmatrixchecksingularm(n, m, info, ref rep, ref x);
                                
                                //
                                // Test SPDMatrixLUSolve()
                                //
                                info = 0;
                                unsetrep(ref rep);
                                cunset2d(ref x);
                                bv = new AP.Complex[n];
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    bv[i_] = b[i_,0];
                                }
                                densesolver.hpdmatrixcholeskysolve(ref cha, n, isupper, ref bv, ref info, ref rep, ref xv);
                                hpderrors = hpderrors | !cmatrixchecksingular(n, info, ref rep, ref xv);
                            }
                        }
                    }
                }
            }
        }
 /*************************************************************************
 Unsets real vector
 *************************************************************************/
 private static void cunset1d(ref AP.Complex[] x)
 {
     x = new AP.Complex[1];
     x[0] = 2*AP.Math.RandomReal()-1;
 }
예제 #28
0
        /*************************************************************************
        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);
                }
            }
        }
        public static bool testcrefl(bool silent)
        {
            bool result = new bool();
            int i = 0;
            int j = 0;
            int k = 0;
            int n = 0;
            int m = 0;
            int maxmn = 0;
            AP.Complex[] x = new AP.Complex[0];
            AP.Complex[] v = new AP.Complex[0];
            AP.Complex[] work = new AP.Complex[0];
            AP.Complex[,] h = new AP.Complex[0,0];
            AP.Complex[,] a = new AP.Complex[0,0];
            AP.Complex[,] b = new AP.Complex[0,0];
            AP.Complex[,] c = new AP.Complex[0,0];
            AP.Complex tmp = 0;
            AP.Complex beta = 0;
            AP.Complex tau = 0;
            double err = 0;
            double mer = 0;
            double mel = 0;
            double meg = 0;
            int pass = 0;
            int passcount = 0;
            bool waserrors = new bool();
            double threshold = 0;
            int i_ = 0;

            threshold = 1000*AP.Math.MachineEpsilon;
            passcount = 1000;
            mer = 0;
            mel = 0;
            meg = 0;
            for(pass=1; pass<=passcount; pass++)
            {
                
                //
                // Task
                //
                n = 1+AP.Math.RandomInteger(10);
                m = 1+AP.Math.RandomInteger(10);
                maxmn = Math.Max(m, n);
                
                //
                // Initialize
                //
                x = new AP.Complex[maxmn+1];
                v = new AP.Complex[maxmn+1];
                work = new AP.Complex[maxmn+1];
                h = new AP.Complex[maxmn+1, maxmn+1];
                a = new AP.Complex[maxmn+1, maxmn+1];
                b = new AP.Complex[maxmn+1, maxmn+1];
                c = new AP.Complex[maxmn+1, maxmn+1];
                
                //
                // GenerateReflection
                //
                for(i=1; i<=n; i++)
                {
                    x[i].x = 2*AP.Math.RandomReal()-1;
                    x[i].y = 2*AP.Math.RandomReal()-1;
                    v[i] = x[i];
                }
                creflections.complexgeneratereflection(ref v, n, ref tau);
                beta = v[1];
                v[1] = 1;
                for(i=1; i<=n; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        if( i==j )
                        {
                            h[i,j] = 1-tau*v[i]*AP.Math.Conj(v[j]);
                        }
                        else
                        {
                            h[i,j] = -(tau*v[i]*AP.Math.Conj(v[j]));
                        }
                    }
                }
                err = 0;
                for(i=1; i<=n; i++)
                {
                    tmp = 0.0;
                    for(i_=1; i_<=n;i_++)
                    {
                        tmp += AP.Math.Conj(h[i_,i])*x[i_];
                    }
                    if( i==1 )
                    {
                        err = Math.Max(err, AP.Math.AbsComplex(tmp-beta));
                    }
                    else
                    {
                        err = Math.Max(err, AP.Math.AbsComplex(tmp));
                    }
                }
                err = Math.Max(err, Math.Abs(beta.y));
                meg = Math.Max(meg, err);
                
                //
                // ApplyReflectionFromTheLeft
                //
                for(i=1; i<=m; i++)
                {
                    x[i].x = 2*AP.Math.RandomReal()-1;
                    x[i].y = 2*AP.Math.RandomReal()-1;
                    v[i] = x[i];
                }
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                        b[i,j] = a[i,j];
                    }
                }
                creflections.complexgeneratereflection(ref v, m, ref tau);
                beta = v[1];
                v[1] = 1;
                creflections.complexapplyreflectionfromtheleft(ref b, tau, ref v, 1, m, 1, n, ref work);
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=m; j++)
                    {
                        if( i==j )
                        {
                            h[i,j] = 1-tau*v[i]*AP.Math.Conj(v[j]);
                        }
                        else
                        {
                            h[i,j] = -(tau*v[i]*AP.Math.Conj(v[j]));
                        }
                    }
                }
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        tmp = 0.0;
                        for(i_=1; i_<=m;i_++)
                        {
                            tmp += h[i,i_]*a[i_,j];
                        }
                        c[i,j] = tmp;
                    }
                }
                err = 0;
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        err = Math.Max(err, AP.Math.AbsComplex(b[i,j]-c[i,j]));
                    }
                }
                mel = Math.Max(mel, err);
                
                //
                // ApplyReflectionFromTheRight
                //
                for(i=1; i<=n; i++)
                {
                    x[i] = 2*AP.Math.RandomReal()-1;
                    v[i] = x[i];
                }
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        a[i,j] = 2*AP.Math.RandomReal()-1;
                        b[i,j] = a[i,j];
                    }
                }
                creflections.complexgeneratereflection(ref v, n, ref tau);
                beta = v[1];
                v[1] = 1;
                creflections.complexapplyreflectionfromtheright(ref b, tau, ref v, 1, m, 1, n, ref work);
                for(i=1; i<=n; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        if( i==j )
                        {
                            h[i,j] = 1-tau*v[i]*AP.Math.Conj(v[j]);
                        }
                        else
                        {
                            h[i,j] = -(tau*v[i]*AP.Math.Conj(v[j]));
                        }
                    }
                }
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        tmp = 0.0;
                        for(i_=1; i_<=n;i_++)
                        {
                            tmp += a[i,i_]*h[i_,j];
                        }
                        c[i,j] = tmp;
                    }
                }
                err = 0;
                for(i=1; i<=m; i++)
                {
                    for(j=1; j<=n; j++)
                    {
                        err = Math.Max(err, AP.Math.AbsComplex(b[i,j]-c[i,j]));
                    }
                }
                mer = Math.Max(mer, err);
            }
            
            //
            // Overflow crash test
            //
            x = new AP.Complex[10+1];
            v = new AP.Complex[10+1];
            for(i=1; i<=10; i++)
            {
                v[i] = AP.Math.MaxRealNumber*0.01*(2*AP.Math.RandomReal()-1);
            }
            creflections.complexgeneratereflection(ref v, 10, ref tau);
            
            //
            // report
            //
            waserrors = (double)(meg)>(double)(threshold) | (double)(mel)>(double)(threshold) | (double)(mer)>(double)(threshold);
            if( !silent )
            {
                System.Console.Write("TESTING COMPLEX REFLECTIONS");
                System.Console.WriteLine();
                System.Console.Write("Generate error:                          ");
                System.Console.Write("{0,5:E3}",meg);
                System.Console.WriteLine();
                System.Console.Write("Apply(L) error:                          ");
                System.Console.Write("{0,5:E3}",mel);
                System.Console.WriteLine();
                System.Console.Write("Apply(R) error:                          ");
                System.Console.Write("{0,5:E3}",mer);
                System.Console.WriteLine();
                System.Console.Write("Threshold:                               ");
                System.Console.Write("{0,5:E3}",threshold);
                System.Console.WriteLine();
                System.Console.Write("Overflow crash test:                     PASSED");
                System.Console.WriteLine();
                if( waserrors )
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
                System.Console.WriteLine();
            }
            result = !waserrors;
            return result;
        }
예제 #30
0
        /*************************************************************************
        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_];
                }
            }
        }
예제 #31
0
        /*************************************************************************
        *  Main unittest subroutine
        *************************************************************************/
        public static bool testsafesolve(bool silent)
        {
            bool   result    = new bool();
            int    maxmn     = 0;
            double threshold = 0;
            bool   rerrors   = new bool();
            bool   cerrors   = new bool();
            bool   waserrors = new bool();
            bool   isupper   = new bool();
            int    trans     = 0;
            bool   isunit    = new bool();
            double scalea    = 0;
            double growth    = 0;
            int    i         = 0;
            int    j         = 0;
            int    n         = 0;
            int    j1        = 0;
            int    j2        = 0;

            AP.Complex cv = 0;
            AP.Complex[,] ca    = new AP.Complex[0, 0];
            AP.Complex[,] cea   = new AP.Complex[0, 0];
            AP.Complex[,] ctmpa = new AP.Complex[0, 0];
            AP.Complex[] cxs = new AP.Complex[0];
            AP.Complex[] cxe = new AP.Complex[0];
            double       rv  = 0;

            double[,] ra    = new double[0, 0];
            double[,] rea   = new double[0, 0];
            double[,] rtmpa = new double[0, 0];
            double[] rxs = new double[0];
            double[] rxe = new double[0];
            int      i_  = 0;

            maxmn     = 30;
            threshold = 100000 * AP.Math.MachineEpsilon;
            rerrors   = false;
            cerrors   = false;
            waserrors = false;

            //
            // Different problems: general tests
            //
            for (n = 1; n <= maxmn; n++)
            {
                //
                // test complex solver with well-conditioned matrix:
                // 1. generate A: fill off-diagonal elements with small values,
                //    diagonal elements are filled with larger values
                // 2. generate 'effective' A
                // 3. prepare task (exact X is stored in CXE, right part - in CXS),
                //    solve and compare CXS and CXE
                //
                isupper = (double)(AP.Math.RandomReal()) > (double)(0.5);
                trans   = AP.Math.RandomInteger(3);
                isunit  = (double)(AP.Math.RandomReal()) > (double)(0.5);
                scalea  = AP.Math.RandomReal() + 0.5;
                ca      = new AP.Complex[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        if (i == j)
                        {
                            ca[i, j].x = (2 * AP.Math.RandomInteger(2) - 1) * (5 + AP.Math.RandomReal());
                            ca[i, j].y = (2 * AP.Math.RandomInteger(2) - 1) * (5 + AP.Math.RandomReal());
                        }
                        else
                        {
                            ca[i, j].x = 0.2 * AP.Math.RandomReal() - 0.1;
                            ca[i, j].y = 0.2 * AP.Math.RandomReal() - 0.1;
                        }
                    }
                }
                cmatrixmakeacopy(ref ca, n, n, ref ctmpa);
                for (i = 0; i <= n - 1; i++)
                {
                    if (isupper)
                    {
                        j1 = 0;
                        j2 = i - 1;
                    }
                    else
                    {
                        j1 = i + 1;
                        j2 = n - 1;
                    }
                    for (j = j1; j <= j2; j++)
                    {
                        ctmpa[i, j] = 0;
                    }
                    if (isunit)
                    {
                        ctmpa[i, i] = 1;
                    }
                }
                cea = new AP.Complex[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    if (trans == 0)
                    {
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            cea[i, i_] = scalea * ctmpa[i, i_];
                        }
                    }
                    if (trans == 1)
                    {
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            cea[i_, i] = scalea * ctmpa[i, i_];
                        }
                    }
                    if (trans == 2)
                    {
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            cea[i_, i] = scalea * AP.Math.Conj(ctmpa[i, i_]);
                        }
                    }
                }
                cxe = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    cxe[i].x = 2 * AP.Math.RandomReal() - 1;
                    cxe[i].y = 2 * AP.Math.RandomReal() - 1;
                }
                cxs = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    cv = 0.0;
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        cv += cea[i, i_] * cxe[i_];
                    }
                    cxs[i] = cv;
                }
                if (safesolve.cmatrixscaledtrsafesolve(ref ca, scalea, n, ref cxs, isupper, trans, isunit, Math.Sqrt(AP.Math.MaxRealNumber)))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        cerrors = cerrors | (double)(AP.Math.AbsComplex(cxs[i] - cxe[i])) > (double)(threshold);
                    }
                }
                else
                {
                    cerrors = true;
                }

                //
                // same with real
                //
                isupper = (double)(AP.Math.RandomReal()) > (double)(0.5);
                trans   = AP.Math.RandomInteger(2);
                isunit  = (double)(AP.Math.RandomReal()) > (double)(0.5);
                scalea  = AP.Math.RandomReal() + 0.5;
                ra      = new double[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        if (i == j)
                        {
                            ra[i, j] = (2 * AP.Math.RandomInteger(2) - 1) * (5 + AP.Math.RandomReal());
                        }
                        else
                        {
                            ra[i, j] = 0.2 * AP.Math.RandomReal() - 0.1;
                        }
                    }
                }
                rmatrixmakeacopy(ref ra, n, n, ref rtmpa);
                for (i = 0; i <= n - 1; i++)
                {
                    if (isupper)
                    {
                        j1 = 0;
                        j2 = i - 1;
                    }
                    else
                    {
                        j1 = i + 1;
                        j2 = n - 1;
                    }
                    for (j = j1; j <= j2; j++)
                    {
                        rtmpa[i, j] = 0;
                    }
                    if (isunit)
                    {
                        rtmpa[i, i] = 1;
                    }
                }
                rea = new double[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    if (trans == 0)
                    {
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            rea[i, i_] = scalea * rtmpa[i, i_];
                        }
                    }
                    if (trans == 1)
                    {
                        for (i_ = 0; i_ <= n - 1; i_++)
                        {
                            rea[i_, i] = scalea * rtmpa[i, i_];
                        }
                    }
                }
                rxe = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    rxe[i] = 2 * AP.Math.RandomReal() - 1;
                }
                rxs = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    rv = 0.0;
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        rv += rea[i, i_] * rxe[i_];
                    }
                    rxs[i] = rv;
                }
                if (safesolve.rmatrixscaledtrsafesolve(ref ra, scalea, n, ref rxs, isupper, trans, isunit, Math.Sqrt(AP.Math.MaxRealNumber)))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        rerrors = rerrors | (double)(Math.Abs(rxs[i] - rxe[i])) > (double)(threshold);
                    }
                }
                else
                {
                    rerrors = true;
                }
            }

            //
            // Special test with diagonal ill-conditioned matrix:
            // * ability to solve it when resulting growth is less than threshold
            // * ability to stop solve when resulting growth is greater than threshold
            //
            // A = diag(1, 1/growth)
            // b = (1, 0.5)
            //
            n        = 2;
            growth   = 10;
            ca       = new AP.Complex[n, n];
            ca[0, 0] = 1;
            ca[0, 1] = 0;
            ca[1, 0] = 0;
            ca[1, 1] = 1 / growth;
            cxs      = new AP.Complex[n];
            cxs[0]   = 1.0;
            cxs[1]   = 0.5;
            cerrors  = cerrors | !safesolve.cmatrixscaledtrsafesolve(ref ca, 1.0, n, ref cxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(3), false, 1.05 * Math.Max(AP.Math.AbsComplex(cxs[1]) * growth, 1.0));
            cerrors  = cerrors | !safesolve.cmatrixscaledtrsafesolve(ref ca, 1.0, n, ref cxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(3), false, 0.95 * Math.Max(AP.Math.AbsComplex(cxs[1]) * growth, 1.0));
            ra       = new double[n, n];
            ra[0, 0] = 1;
            ra[0, 1] = 0;
            ra[1, 0] = 0;
            ra[1, 1] = 1 / growth;
            rxs      = new double[n];
            rxs[0]   = 1.0;
            rxs[1]   = 0.5;
            rerrors  = rerrors | !safesolve.rmatrixscaledtrsafesolve(ref ra, 1.0, n, ref rxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(2), false, 1.05 * Math.Max(Math.Abs(rxs[1]) * growth, 1.0));
            rerrors  = rerrors | !safesolve.rmatrixscaledtrsafesolve(ref ra, 1.0, n, ref rxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(2), false, 0.95 * Math.Max(Math.Abs(rxs[1]) * growth, 1.0));

            //
            // Special test with diagonal degenerate matrix:
            // * ability to solve it when resulting growth is less than threshold
            // * ability to stop solve when resulting growth is greater than threshold
            //
            // A = diag(1, 0)
            // b = (1, 0.5)
            //
            n        = 2;
            ca       = new AP.Complex[n, n];
            ca[0, 0] = 1;
            ca[0, 1] = 0;
            ca[1, 0] = 0;
            ca[1, 1] = 0;
            cxs      = new AP.Complex[n];
            cxs[0]   = 1.0;
            cxs[1]   = 0.5;
            cerrors  = cerrors | safesolve.cmatrixscaledtrsafesolve(ref ca, 1.0, n, ref cxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(3), false, Math.Sqrt(AP.Math.MaxRealNumber));
            ra       = new double[n, n];
            ra[0, 0] = 1;
            ra[0, 1] = 0;
            ra[1, 0] = 0;
            ra[1, 1] = 0;
            rxs      = new double[n];
            rxs[0]   = 1.0;
            rxs[1]   = 0.5;
            rerrors  = rerrors | safesolve.rmatrixscaledtrsafesolve(ref ra, 1.0, n, ref rxs, (double)(AP.Math.RandomReal()) > (double)(0.5), AP.Math.RandomInteger(2), false, Math.Sqrt(AP.Math.MaxRealNumber));

            //
            // report
            //
            waserrors = rerrors | cerrors;
            if (!silent)
            {
                System.Console.Write("TESTING SAFE TR SOLVER");
                System.Console.WriteLine();
                System.Console.Write("REAL:                                    ");
                if (!rerrors)
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                System.Console.Write("COMPLEX:                                 ");
                if (!cerrors)
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                if (waserrors)
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
                System.Console.WriteLine();
            }
            result = !waserrors;
            return(result);
        }
예제 #32
0
        /*************************************************************************
        Dense solver. Same as RMatrixLUSolve(), but for  HPD matrices  represented
        by their Cholesky decomposition.

        Algorithm features:
        * automatic detection of degenerate cases
        * O(N^2) complexity
        * condition number estimation
        * matrix is represented by its upper or lower triangle

        No iterative refinement is provided because such partial representation of
        matrix does not allow efficient calculation of extra-precise  matrix-vector
        products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
        need iterative refinement.

        INPUT PARAMETERS
            CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
                        SPDMatrixCholesky result
            N       -   size of A
            IsUpper -   what half of CHA is provided
            B       -   array[0..N-1], right part

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolve
            Rep     -   same as in RMatrixSolve
            X       -   same as in RMatrixSolve

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void hpdmatrixcholeskysolve(ref AP.Complex[,] cha,
            int n,
            bool isupper,
            ref AP.Complex[] b,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[] x)
        {
            AP.Complex[,] bm = new AP.Complex[0,0];
            AP.Complex[,] xm = new AP.Complex[0,0];
            int i_ = 0;

            if( n<=0 )
            {
                info = -1;
                return;
            }
            bm = new AP.Complex[n, 1];
            for(i_=0; i_<=n-1;i_++)
            {
                bm[i_,0] = b[i_];
            }
            hpdmatrixcholeskysolvem(ref cha, n, isupper, ref bm, 1, ref info, ref rep, ref xm);
            x = new AP.Complex[n];
            for(i_=0; i_<=n-1;i_++)
            {
                x[i_] = xm[i_,0];
            }
        }
예제 #33
0
        /*************************************************************************
        Internal LU solver

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        private static void cmatrixlusolveinternal(ref AP.Complex[,] lua,
            ref int[] p,
            double scalea,
            int n,
            ref AP.Complex[,] a,
            bool havea,
            ref AP.Complex[,] b,
            int m,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            int i = 0;
            int j = 0;
            int k = 0;
            int rfs = 0;
            int nrfs = 0;
            AP.Complex[] xc = new AP.Complex[0];
            AP.Complex[] y = new AP.Complex[0];
            AP.Complex[] bc = new AP.Complex[0];
            AP.Complex[] xa = new AP.Complex[0];
            AP.Complex[] xb = new AP.Complex[0];
            AP.Complex[] tx = new AP.Complex[0];
            double[] tmpbuf = new double[0];
            AP.Complex v = 0;
            double verr = 0;
            double mxb = 0;
            double scaleright = 0;
            bool smallerr = new bool();
            bool terminatenexttime = new bool();
            int i_ = 0;

            System.Diagnostics.Debug.Assert((double)(scalea)>(double)(0));
            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            for(i=0; i<=n-1; i++)
            {
                if( p[i]>n-1 | p[i]<i )
                {
                    info = -1;
                    return;
                }
            }
            x = new AP.Complex[n, m];
            y = new AP.Complex[n];
            xc = new AP.Complex[n];
            bc = new AP.Complex[n];
            tx = new AP.Complex[n];
            xa = new AP.Complex[n+1];
            xb = new AP.Complex[n+1];
            tmpbuf = new double[2*n+2];
            
            //
            // estimate condition number, test for near singularity
            //
            rep.r1 = rcond.cmatrixlurcond1(ref lua, n);
            rep.rinf = rcond.cmatrixlurcondinf(ref lua, 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<=m-1; j++)
                    {
                        x[i,j] = 0;
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }
            info = 1;
            
            //
            // solve
            //
            for(k=0; k<=m-1; k++)
            {
                
                //
                // copy B to contiguous storage
                //
                for(i_=0; i_<=n-1;i_++)
                {
                    bc[i_] = b[i_,k];
                }
                
                //
                // Scale right part:
                // * MX stores max(|Bi|)
                // * ScaleRight stores actual scaling applied to B when solving systems
                //   it is chosen to make |scaleRight*b| close to 1.
                //
                mxb = 0;
                for(i=0; i<=n-1; i++)
                {
                    mxb = Math.Max(mxb, AP.Math.AbsComplex(bc[i]));
                }
                if( (double)(mxb)==(double)(0) )
                {
                    mxb = 1;
                }
                scaleright = 1/mxb;
                
                //
                // First, non-iterative part of solution process.
                // We use separate code for this task because
                // XDot is quite slow and we want to save time.
                //
                for(i_=0; i_<=n-1;i_++)
                {
                    xc[i_] = scaleright*bc[i_];
                }
                cbasiclusolve(ref lua, ref p, scalea, n, ref xc, ref tx);
                
                //
                // Iterative refinement of xc:
                // * calculate r = bc-A*xc using extra-precise dot product
                // * solve A*y = r
                // * update x:=x+r
                //
                // This cycle is executed until one of two things happens:
                // 1. maximum number of iterations reached
                // 2. last iteration decreased error to the lower limit
                //
                if( havea )
                {
                    nrfs = densesolverrfsmax(n, rep.r1, rep.rinf);
                    terminatenexttime = false;
                    for(rfs=0; rfs<=nrfs-1; rfs++)
                    {
                        if( terminatenexttime )
                        {
                            break;
                        }
                        
                        //
                        // generate right part
                        //
                        smallerr = true;
                        for(i_=0; i_<=n-1;i_++)
                        {
                            xb[i_] = xc[i_];
                        }
                        for(i=0; i<=n-1; i++)
                        {
                            for(i_=0; i_<=n-1;i_++)
                            {
                                xa[i_] = scalea*a[i,i_];
                            }
                            xa[n] = -1;
                            xb[n] = scaleright*bc[i];
                            xblas.xcdot(ref xa, ref xb, n+1, ref tmpbuf, ref v, ref verr);
                            y[i] = -v;
                            smallerr = smallerr & (double)(AP.Math.AbsComplex(v))<(double)(4*verr);
                        }
                        if( smallerr )
                        {
                            terminatenexttime = true;
                        }
                        
                        //
                        // solve and update
                        //
                        cbasiclusolve(ref lua, ref p, scalea, n, ref y, ref tx);
                        for(i_=0; i_<=n-1;i_++)
                        {
                            xc[i_] = xc[i_] + y[i_];
                        }
                    }
                }
                
                //
                // Store xc.
                // Post-scale result.
                //
                v = scalea*mxb;
                for(i_=0; i_<=n-1;i_++)
                {
                    x[i_,k] = v*xc[i_];
                }
            }
        }
예제 #34
0
        /*************************************************************************
        Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices  represented
        by their Cholesky decomposition.

        Algorithm features:
        * automatic detection of degenerate cases
        * O(M*N^2) complexity
        * condition number estimation
        * matrix is represented by its upper or lower triangle

        No iterative refinement is provided because such partial representation of
        matrix does not allow efficient calculation of extra-precise  matrix-vector
        products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
        need iterative refinement.

        INPUT PARAMETERS
            CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
                        HPDMatrixCholesky result
            N       -   size of CHA
            IsUpper -   what half of CHA is provided
            B       -   array[0..N-1,0..M-1], right part
            M       -   right part size

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolve
            Rep     -   same as in RMatrixSolve
            X       -   same as in RMatrixSolve

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void hpdmatrixcholeskysolvem(ref AP.Complex[,] cha,
            int n,
            bool isupper,
            ref AP.Complex[,] b,
            int m,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            AP.Complex[,] emptya = new AP.Complex[0,0];
            double sqrtscalea = 0;
            int i = 0;
            int j = 0;
            int j1 = 0;
            int j2 = 0;

            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            
            //
            // 1. scale matrix, max(|U[i,j]|)
            // 2. factorize scaled matrix
            // 3. solve
            //
            sqrtscalea = 0;
            for(i=0; i<=n-1; i++)
            {
                if( isupper )
                {
                    j1 = i;
                    j2 = n-1;
                }
                else
                {
                    j1 = 0;
                    j2 = i;
                }
                for(j=j1; j<=j2; j++)
                {
                    sqrtscalea = Math.Max(sqrtscalea, AP.Math.AbsComplex(cha[i,j]));
                }
            }
            if( (double)(sqrtscalea)==(double)(0) )
            {
                sqrtscalea = 1;
            }
            sqrtscalea = 1/sqrtscalea;
            hpdmatrixcholeskysolveinternal(ref cha, sqrtscalea, n, isupper, ref emptya, false, ref b, m, ref info, ref rep, ref x);
        }
예제 #35
0
        /*************************************************************************
        Dense solver. Same as RMatrixSolveM(), but for Hermitian positive definite
        matrices.

        Algorithm features:
        * automatic detection of degenerate cases
        * condition number estimation
        * O(N^3+M*N^2) complexity
        * matrix is represented by its upper or lower triangle

        No iterative refinement is provided because such partial representation of
        matrix does not allow efficient calculation of extra-precise  matrix-vector
        products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
        need iterative refinement.

        INPUT PARAMETERS
            A       -   array[0..N-1,0..N-1], system matrix
            N       -   size of A
            IsUpper -   what half of A is provided
            B       -   array[0..N-1,0..M-1], right part
            M       -   right part size

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolve.
                        Returns -3 for non-HPD matrices.
            Rep     -   same as in RMatrixSolve
            X       -   same as in RMatrixSolve

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void hpdmatrixsolvem(ref AP.Complex[,] a,
            int n,
            bool isupper,
            ref AP.Complex[,] b,
            int m,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            AP.Complex[,] da = new AP.Complex[0,0];
            double sqrtscalea = 0;
            int i = 0;
            int j = 0;
            int j1 = 0;
            int j2 = 0;
            int i_ = 0;

            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            da = new AP.Complex[n, n];
            
            //
            // 1. scale matrix, max(|A[i,j]|)
            // 2. factorize scaled matrix
            // 3. solve
            //
            sqrtscalea = 0;
            for(i=0; i<=n-1; i++)
            {
                if( isupper )
                {
                    j1 = i;
                    j2 = n-1;
                }
                else
                {
                    j1 = 0;
                    j2 = i;
                }
                for(j=j1; j<=j2; j++)
                {
                    sqrtscalea = Math.Max(sqrtscalea, AP.Math.AbsComplex(a[i,j]));
                }
            }
            if( (double)(sqrtscalea)==(double)(0) )
            {
                sqrtscalea = 1;
            }
            sqrtscalea = 1/sqrtscalea;
            sqrtscalea = Math.Sqrt(sqrtscalea);
            for(i=0; i<=n-1; i++)
            {
                if( isupper )
                {
                    j1 = i;
                    j2 = n-1;
                }
                else
                {
                    j1 = 0;
                    j2 = i;
                }
                for(i_=j1; i_<=j2;i_++)
                {
                    da[i,i_] = a[i,i_];
                }
            }
            if( !trfac.hpdmatrixcholesky(ref da, n, isupper) )
            {
                x = new AP.Complex[n, m];
                for(i=0; i<=n-1; i++)
                {
                    for(j=0; j<=m-1; j++)
                    {
                        x[i,j] = 0;
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }
            info = 1;
            hpdmatrixcholeskysolveinternal(ref da, sqrtscalea, n, isupper, ref a, true, ref b, m, ref info, ref rep, ref x);
        }
예제 #36
0
        /*************************************************************************
        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;
            }
        }
예제 #37
0
        /*************************************************************************
        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;
        }
예제 #38
0
        /*************************************************************************
        Dense solver. Same as RMatrixLUSolveM(), but for complex matrices.

        Algorithm features:
        * automatic detection of degenerate cases
        * O(M*N^2) complexity
        * condition number estimation

        No iterative refinement  is provided because exact form of original matrix
        is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve  if  you
        need iterative refinement.

        INPUT PARAMETERS
            LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
            P       -   array[0..N-1], pivots array, RMatrixLU result
            N       -   size of A
            B       -   array[0..N-1,0..M-1], right part
            M       -   right part size

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolve
            Rep     -   same as in RMatrixSolve
            X       -   same as in RMatrixSolve

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixlusolvem(ref AP.Complex[,] lua,
            ref int[] p,
            int n,
            ref AP.Complex[,] b,
            int m,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            AP.Complex[,] emptya = new AP.Complex[0,0];
            int i = 0;
            int j = 0;
            double scalea = 0;

            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            
            //
            // 1. scale matrix, max(|U[i,j]|)
            //    we assume that LU is in its normal form, i.e. |L[i,j]|<=1
            // 2. solve
            //
            scalea = 0;
            for(i=0; i<=n-1; i++)
            {
                for(j=i; j<=n-1; j++)
                {
                    scalea = Math.Max(scalea, AP.Math.AbsComplex(lua[i,j]));
                }
            }
            if( (double)(scalea)==(double)(0) )
            {
                scalea = 1;
            }
            scalea = 1/scalea;
            cmatrixlusolveinternal(ref lua, ref p, scalea, n, ref emptya, false, ref b, m, ref info, ref rep, ref x);
        }
예제 #39
0
        /*************************************************************************
        *  1-dimensional real FFT.
        *
        *  Algorithm has O(N*logN) complexity for any N (composite or prime).
        *
        *  INPUT PARAMETERS
        *   A   -   array[0..N-1] - real function to be transformed
        *   N   -   problem size
        *
        *  OUTPUT PARAMETERS
        *   F   -   DFT of a input array, array[0..N-1]
        *           F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1)
        *
        *  NOTE:
        *   F[] satisfies symmetry property F[k] = conj(F[N-k]),  so just one half
        *  of  array  is  usually needed. But for convinience subroutine returns full
        *  complex array (with frequencies above N/2), so its result may be  used  by
        *  other FFT-related subroutines.
        *
        *
        *  -- ALGLIB --
        *    Copyright 01.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fftr1d(ref double[] a,
                                  int n,
                                  ref AP.Complex[] f)
        {
            int i   = 0;
            int n2  = 0;
            int idx = 0;

            AP.Complex    hn   = 0;
            AP.Complex    hmnc = 0;
            AP.Complex    v    = 0;
            double[]      buf  = new double[0];
            ftbase.ftplan plan = new ftbase.ftplan();
            int           i_   = 0;

            System.Diagnostics.Debug.Assert(n > 0, "FFTR1D: incorrect N!");

            //
            // Special cases:
            // * N=1, FFT is just identity transform.
            // * N=2, FFT is simple too
            //
            // After this block we assume that N is strictly greater than 2
            //
            if (n == 1)
            {
                f    = new AP.Complex[1];
                f[0] = a[0];
                return;
            }
            if (n == 2)
            {
                f      = new AP.Complex[2];
                f[0].x = a[0] + a[1];
                f[0].y = 0;
                f[1].x = a[0] - a[1];
                f[1].y = 0;
                return;
            }

            //
            // Choose between odd-size and even-size FFTs
            //
            if (n % 2 == 0)
            {
                //
                // even-size real FFT, use reduction to the complex task
                //
                n2  = n / 2;
                buf = new double[n];
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    buf[i_] = a[i_];
                }
                ftbase.ftbasegeneratecomplexfftplan(n2, ref plan);
                ftbase.ftbaseexecuteplan(ref buf, 0, n2, ref plan);
                f = new AP.Complex[n];
                for (i = 0; i <= n2; i++)
                {
                    idx    = 2 * (i % n2);
                    hn.x   = buf[idx + 0];
                    hn.y   = buf[idx + 1];
                    idx    = 2 * ((n2 - i) % n2);
                    hmnc.x = buf[idx + 0];
                    hmnc.y = -buf[idx + 1];
                    v.x    = -Math.Sin(-(2 * Math.PI * i / n));
                    v.y    = Math.Cos(-(2 * Math.PI * i / n));
                    f[i]   = hn + hmnc - v * (hn - hmnc);
                    f[i].x = 0.5 * f[i].x;
                    f[i].y = 0.5 * f[i].y;
                }
                for (i = n2 + 1; i <= n - 1; i++)
                {
                    f[i] = AP.Math.Conj(f[n - i]);
                }
                return;
            }
            else
            {
                //
                // use complex FFT
                //
                f = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    f[i] = a[i];
                }
                fftc1d(ref f, n);
                return;
            }
        }
예제 #40
0
        /*************************************************************************
        Dense solver. Same as RMatrixMixedSolve(), but for complex matrices.

        Algorithm features:
        * automatic detection of degenerate cases
        * condition number estimation
        * iterative refinement
        * O(N^2) complexity

        INPUT PARAMETERS
            A       -   array[0..N-1,0..N-1], system matrix
            LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
            P       -   array[0..N-1], pivots array, CMatrixLU result
            N       -   size of A
            B       -   array[0..N-1], right part

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolveM
            Rep     -   same as in RMatrixSolveM
            X       -   same as in RMatrixSolveM

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixmixedsolve(ref AP.Complex[,] a,
            ref AP.Complex[,] lua,
            ref int[] p,
            int n,
            ref AP.Complex[] b,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[] x)
        {
            AP.Complex[,] bm = new AP.Complex[0,0];
            AP.Complex[,] xm = new AP.Complex[0,0];
            int i_ = 0;

            if( n<=0 )
            {
                info = -1;
                return;
            }
            bm = new AP.Complex[n, 1];
            for(i_=0; i_<=n-1;i_++)
            {
                bm[i_,0] = b[i_];
            }
            cmatrixmixedsolvem(ref a, ref lua, ref p, n, ref bm, 1, ref info, ref rep, ref xm);
            x = new AP.Complex[n];
            for(i_=0; i_<=n-1;i_++)
            {
                x[i_] = xm[i_,0];
            }
        }
예제 #41
0
        /*************************************************************************
        *  Test
        *************************************************************************/
        public static bool testconv(bool silent)
        {
            bool result   = new bool();
            int  m        = 0;
            int  n        = 0;
            int  i        = 0;
            int  rkind    = 0;
            int  circkind = 0;

            double[]     ra         = new double[0];
            double[]     rb         = new double[0];
            double[]     rr1        = new double[0];
            double[]     rr2        = new double[0];
            AP.Complex[] ca         = new AP.Complex[0];
            AP.Complex[] cb         = new AP.Complex[0];
            AP.Complex[] cr1        = new AP.Complex[0];
            AP.Complex[] cr2        = new AP.Complex[0];
            int          maxn       = 0;
            double       referr     = 0;
            double       refrerr    = 0;
            double       inverr     = 0;
            double       invrerr    = 0;
            double       errtol     = 0;
            bool         referrors  = new bool();
            bool         refrerrors = new bool();
            bool         inverrors  = new bool();
            bool         invrerrors = new bool();
            bool         waserrors  = new bool();

            maxn       = 32;
            errtol     = 100000 * Math.Pow(maxn, (double)(3) / (double)(2)) * AP.Math.MachineEpsilon;
            referrors  = false;
            refrerrors = false;
            inverrors  = false;
            invrerrors = false;
            waserrors  = false;

            //
            // Test against reference O(N^2) implementation.
            //
            // Automatic ConvC1D() and different algorithms of ConvC1DX() are tested.
            //
            referr  = 0;
            refrerr = 0;
            for (m = 1; m <= maxn; m++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    for (circkind = 0; circkind <= 1; circkind++)
                    {
                        for (rkind = -3; rkind <= 1; rkind++)
                        {
                            //
                            // skip impossible combinations of parameters:
                            // * circular convolution, M<N, RKind<>-3 - internal subroutine does not support M<N.
                            //
                            if (circkind != 0 & m < n & rkind != -3)
                            {
                                continue;
                            }

                            //
                            // Complex convolution
                            //
                            ca = new AP.Complex[m];
                            for (i = 0; i <= m - 1; i++)
                            {
                                ca[i].x = 2 * AP.Math.RandomReal() - 1;
                                ca[i].y = 2 * AP.Math.RandomReal() - 1;
                            }
                            cb = new AP.Complex[n];
                            for (i = 0; i <= n - 1; i++)
                            {
                                cb[i].x = 2 * AP.Math.RandomReal() - 1;
                                cb[i].y = 2 * AP.Math.RandomReal() - 1;
                            }
                            cr1 = new AP.Complex[1];
                            if (rkind == -3)
                            {
                                //
                                // test wrapper subroutine:
                                // * circular/non-circular
                                //
                                if (circkind == 0)
                                {
                                    conv.convc1d(ref ca, m, ref cb, n, ref cr1);
                                }
                                else
                                {
                                    conv.convc1dcircular(ref ca, m, ref cb, n, ref cr1);
                                }
                            }
                            else
                            {
                                //
                                // test internal subroutine
                                //
                                if (m >= n)
                                {
                                    //
                                    // test internal subroutine:
                                    // * circular/non-circular mode
                                    //
                                    conv.convc1dx(ref ca, m, ref cb, n, circkind != 0, rkind, 0, ref cr1);
                                }
                                else
                                {
                                    //
                                    // test internal subroutine - circular mode only
                                    //
                                    System.Diagnostics.Debug.Assert(circkind == 0, "Convolution test: internal error!");
                                    conv.convc1dx(ref cb, n, ref ca, m, false, rkind, 0, ref cr1);
                                }
                            }
                            if (circkind == 0)
                            {
                                refconvc1d(ref ca, m, ref cb, n, ref cr2);
                            }
                            else
                            {
                                refconvc1dcircular(ref ca, m, ref cb, n, ref cr2);
                            }
                            if (circkind == 0)
                            {
                                for (i = 0; i <= m + n - 2; i++)
                                {
                                    referr = Math.Max(referr, AP.Math.AbsComplex(cr1[i] - cr2[i]));
                                }
                            }
                            else
                            {
                                for (i = 0; i <= m - 1; i++)
                                {
                                    referr = Math.Max(referr, AP.Math.AbsComplex(cr1[i] - cr2[i]));
                                }
                            }

                            //
                            // Real convolution
                            //
                            ra = new double[m];
                            for (i = 0; i <= m - 1; i++)
                            {
                                ra[i] = 2 * AP.Math.RandomReal() - 1;
                            }
                            rb = new double[n];
                            for (i = 0; i <= n - 1; i++)
                            {
                                rb[i] = 2 * AP.Math.RandomReal() - 1;
                            }
                            rr1 = new double[1];
                            if (rkind == -3)
                            {
                                //
                                // test wrapper subroutine:
                                // * circular/non-circular
                                //
                                if (circkind == 0)
                                {
                                    conv.convr1d(ref ra, m, ref rb, n, ref rr1);
                                }
                                else
                                {
                                    conv.convr1dcircular(ref ra, m, ref rb, n, ref rr1);
                                }
                            }
                            else
                            {
                                if (m >= n)
                                {
                                    //
                                    // test internal subroutine:
                                    // * circular/non-circular mode
                                    //
                                    conv.convr1dx(ref ra, m, ref rb, n, circkind != 0, rkind, 0, ref rr1);
                                }
                                else
                                {
                                    //
                                    // test internal subroutine - non-circular mode only
                                    //
                                    conv.convr1dx(ref rb, n, ref ra, m, circkind != 0, rkind, 0, ref rr1);
                                }
                            }
                            if (circkind == 0)
                            {
                                refconvr1d(ref ra, m, ref rb, n, ref rr2);
                            }
                            else
                            {
                                refconvr1dcircular(ref ra, m, ref rb, n, ref rr2);
                            }
                            if (circkind == 0)
                            {
                                for (i = 0; i <= m + n - 2; i++)
                                {
                                    refrerr = Math.Max(refrerr, Math.Abs(rr1[i] - rr2[i]));
                                }
                            }
                            else
                            {
                                for (i = 0; i <= m - 1; i++)
                                {
                                    refrerr = Math.Max(refrerr, Math.Abs(rr1[i] - rr2[i]));
                                }
                            }
                        }
                    }
                }
            }
            referrors  = referrors | (double)(referr) > (double)(errtol);
            refrerrors = refrerrors | (double)(refrerr) > (double)(errtol);

            //
            // Test inverse convolution
            //
            inverr  = 0;
            invrerr = 0;
            for (m = 1; m <= maxn; m++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    //
                    // Complex circilar and non-circular
                    //
                    ca = new AP.Complex[m];
                    for (i = 0; i <= m - 1; i++)
                    {
                        ca[i].x = 2 * AP.Math.RandomReal() - 1;
                        ca[i].y = 2 * AP.Math.RandomReal() - 1;
                    }
                    cb = new AP.Complex[n];
                    for (i = 0; i <= n - 1; i++)
                    {
                        cb[i].x = 2 * AP.Math.RandomReal() - 1;
                        cb[i].y = 2 * AP.Math.RandomReal() - 1;
                    }
                    cr1 = new AP.Complex[1];
                    cr2 = new AP.Complex[1];
                    conv.convc1d(ref ca, m, ref cb, n, ref cr2);
                    conv.convc1dinv(ref cr2, m + n - 1, ref cb, n, ref cr1);
                    for (i = 0; i <= m - 1; i++)
                    {
                        inverr = Math.Max(inverr, AP.Math.AbsComplex(cr1[i] - ca[i]));
                    }
                    cr1 = new AP.Complex[1];
                    cr2 = new AP.Complex[1];
                    conv.convc1dcircular(ref ca, m, ref cb, n, ref cr2);
                    conv.convc1dcircularinv(ref cr2, m, ref cb, n, ref cr1);
                    for (i = 0; i <= m - 1; i++)
                    {
                        inverr = Math.Max(inverr, AP.Math.AbsComplex(cr1[i] - ca[i]));
                    }

                    //
                    // Real circilar and non-circular
                    //
                    ra = new double[m];
                    for (i = 0; i <= m - 1; i++)
                    {
                        ra[i] = 2 * AP.Math.RandomReal() - 1;
                    }
                    rb = new double[n];
                    for (i = 0; i <= n - 1; i++)
                    {
                        rb[i] = 2 * AP.Math.RandomReal() - 1;
                    }
                    rr1 = new double[1];
                    rr2 = new double[1];
                    conv.convr1d(ref ra, m, ref rb, n, ref rr2);
                    conv.convr1dinv(ref rr2, m + n - 1, ref rb, n, ref rr1);
                    for (i = 0; i <= m - 1; i++)
                    {
                        invrerr = Math.Max(invrerr, Math.Abs(rr1[i] - ra[i]));
                    }
                    rr1 = new double[1];
                    rr2 = new double[1];
                    conv.convr1dcircular(ref ra, m, ref rb, n, ref rr2);
                    conv.convr1dcircularinv(ref rr2, m, ref rb, n, ref rr1);
                    for (i = 0; i <= m - 1; i++)
                    {
                        invrerr = Math.Max(invrerr, Math.Abs(rr1[i] - ra[i]));
                    }
                }
            }
            inverrors  = inverrors | (double)(inverr) > (double)(errtol);
            invrerrors = invrerrors | (double)(invrerr) > (double)(errtol);

            //
            // end
            //
            waserrors = referrors | refrerrors | inverrors | invrerrors;
            if (!silent)
            {
                System.Console.Write("TESTING CONVOLUTION");
                System.Console.WriteLine();
                System.Console.Write("FINAL RESULT:                             ");
                if (waserrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE COMPLEX CONV:         ");
                if (referrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE REAL CONV:            ");
                if (refrerrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* COMPLEX INVERSE:                        ");
                if (inverrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* REAL INVERSE:                           ");
                if (invrerrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                if (waserrors)
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
            }
            result = !waserrors;
            return(result);
        }
예제 #42
0
        /*************************************************************************
        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;
        }
        /*************************************************************************
        Real test
        *************************************************************************/
        private static void testcsolver(int maxn,
            int maxm,
            int passcount,
            double threshold,
            ref bool cerrors,
            ref bool rfserrors)
        {
            AP.Complex[,] a = new AP.Complex[0,0];
            AP.Complex[,] lua = new AP.Complex[0,0];
            AP.Complex[,] atmp = new AP.Complex[0,0];
            int[] p = new int[0];
            AP.Complex[,] xe = new AP.Complex[0,0];
            AP.Complex[,] b = new AP.Complex[0,0];
            AP.Complex[] bv = new AP.Complex[0];
            int i = 0;
            int j = 0;
            int k = 0;
            int n = 0;
            int m = 0;
            int pass = 0;
            int taskkind = 0;
            double mx = 0;
            double verr = 0;
            AP.Complex v = 0;
            int info = 0;
            densesolver.densesolverreport rep = new densesolver.densesolverreport();
            densesolver.densesolverlsreport repls = new densesolver.densesolverlsreport();
            AP.Complex[,] x = new AP.Complex[0,0];
            AP.Complex[] xv = new AP.Complex[0];
            AP.Complex[] y = new AP.Complex[0];
            double[] tx = new double[0];
            int i_ = 0;

            
            //
            // General square matrices:
            // * test general solvers
            // * test least squares solver
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    for(m=1; m<=maxm; m++)
                    {
                        
                        //
                        // ********************************************************
                        // WELL CONDITIONED TASKS
                        // ability to find correct solution is tested
                        // ********************************************************
                        //
                        // 1. generate random well conditioned matrix A.
                        // 2. generate random solution vector xe
                        // 3. generate right part b=A*xe
                        // 4. test different methods on original A
                        //
                        matgen.cmatrixrndcond(n, 1000, ref a);
                        cmatrixmakeacopy(ref a, n, n, ref lua);
                        trfac.cmatrixlu(ref lua, n, n, ref p);
                        xe = new AP.Complex[n, m];
                        for(i=0; i<=n-1; i++)
                        {
                            for(j=0; j<=m-1; j++)
                            {
                                xe[i,j].x = 2*AP.Math.RandomReal()-1;
                                xe[i,j].y = 2*AP.Math.RandomReal()-1;
                            }
                        }
                        b = new AP.Complex[n, m];
                        for(i=0; i<=n-1; i++)
                        {
                            for(j=0; j<=m-1; j++)
                            {
                                v = 0.0;
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    v += a[i,i_]*xe[i_,j];
                                }
                                b[i,j] = v;
                            }
                        }
                        
                        //
                        // Test solvers
                        //
                        info = 0;
                        unsetrep(ref rep);
                        cunset2d(ref x);
                        densesolver.cmatrixsolvem(ref a, n, ref b, m, (double)(AP.Math.RandomReal())>(double)(0.5), ref info, ref rep, ref x);
                        cerrors = cerrors | !cmatrixchecksolutionm(ref xe, n, m, threshold, info, ref rep, ref x);
                        info = 0;
                        unsetrep(ref rep);
                        cunset1d(ref xv);
                        bv = new AP.Complex[n];
                        for(i_=0; i_<=n-1;i_++)
                        {
                            bv[i_] = b[i_,0];
                        }
                        densesolver.cmatrixsolve(ref a, n, ref bv, ref info, ref rep, ref xv);
                        cerrors = cerrors | !cmatrixchecksolution(ref xe, n, threshold, info, ref rep, ref xv);
                        info = 0;
                        unsetrep(ref rep);
                        cunset2d(ref x);
                        densesolver.cmatrixlusolvem(ref lua, ref p, n, ref b, m, ref info, ref rep, ref x);
                        cerrors = cerrors | !cmatrixchecksolutionm(ref xe, n, m, threshold, info, ref rep, ref x);
                        info = 0;
                        unsetrep(ref rep);
                        cunset1d(ref xv);
                        bv = new AP.Complex[n];
                        for(i_=0; i_<=n-1;i_++)
                        {
                            bv[i_] = b[i_,0];
                        }
                        densesolver.cmatrixlusolve(ref lua, ref p, n, ref bv, ref info, ref rep, ref xv);
                        cerrors = cerrors | !cmatrixchecksolution(ref xe, n, threshold, info, ref rep, ref xv);
                        info = 0;
                        unsetrep(ref rep);
                        cunset2d(ref x);
                        densesolver.cmatrixmixedsolvem(ref a, ref lua, ref p, n, ref b, m, ref info, ref rep, ref x);
                        cerrors = cerrors | !cmatrixchecksolutionm(ref xe, n, m, threshold, info, ref rep, ref x);
                        info = 0;
                        unsetrep(ref rep);
                        cunset1d(ref xv);
                        bv = new AP.Complex[n];
                        for(i_=0; i_<=n-1;i_++)
                        {
                            bv[i_] = b[i_,0];
                        }
                        densesolver.cmatrixmixedsolve(ref a, ref lua, ref p, n, ref bv, ref info, ref rep, ref xv);
                        cerrors = cerrors | !cmatrixchecksolution(ref xe, n, threshold, info, ref rep, ref xv);
                        
                        //
                        // ********************************************************
                        // EXACTLY SINGULAR MATRICES
                        // ability to detect singularity is tested
                        // ********************************************************
                        //
                        // 1. generate different types of singular matrices:
                        //    * zero
                        //    * with zero columns
                        //    * with zero rows
                        //    * with equal rows/columns
                        // 2. generate random solution vector xe
                        // 3. generate right part b=A*xe
                        // 4. test different methods
                        //
                        for(taskkind=0; taskkind<=4; taskkind++)
                        {
                            cunset2d(ref a);
                            if( taskkind==0 )
                            {
                                
                                //
                                // all zeros
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j] = 0;
                                    }
                                }
                            }
                            if( taskkind==1 )
                            {
                                
                                //
                                // there is zero column
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                    }
                                }
                                k = AP.Math.RandomInteger(n);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[i_,k] = 0*a[i_,k];
                                }
                            }
                            if( taskkind==2 )
                            {
                                
                                //
                                // there is zero row
                                //
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                    }
                                }
                                k = AP.Math.RandomInteger(n);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[k,i_] = 0*a[k,i_];
                                }
                            }
                            if( taskkind==3 )
                            {
                                
                                //
                                // equal columns
                                //
                                if( n<2 )
                                {
                                    continue;
                                }
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                    }
                                }
                                k = 1+AP.Math.RandomInteger(n-1);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[i_,0] = a[i_,k];
                                }
                            }
                            if( taskkind==4 )
                            {
                                
                                //
                                // equal rows
                                //
                                if( n<2 )
                                {
                                    continue;
                                }
                                a = new AP.Complex[n, n];
                                for(i=0; i<=n-1; i++)
                                {
                                    for(j=0; j<=n-1; j++)
                                    {
                                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                                    }
                                }
                                k = 1+AP.Math.RandomInteger(n-1);
                                for(i_=0; i_<=n-1;i_++)
                                {
                                    a[0,i_] = a[k,i_];
                                }
                            }
                            xe = new AP.Complex[n, m];
                            for(i=0; i<=n-1; i++)
                            {
                                for(j=0; j<=m-1; j++)
                                {
                                    xe[i,j] = 2*AP.Math.RandomReal()-1;
                                }
                            }
                            b = new AP.Complex[n, m];
                            for(i=0; i<=n-1; i++)
                            {
                                for(j=0; j<=m-1; j++)
                                {
                                    v = 0.0;
                                    for(i_=0; i_<=n-1;i_++)
                                    {
                                        v += a[i,i_]*xe[i_,j];
                                    }
                                    b[i,j] = v;
                                }
                            }
                            cmatrixmakeacopy(ref a, n, n, ref lua);
                            trfac.cmatrixlu(ref lua, n, n, ref p);
                            
                            //
                            // Test CMatrixSolveM()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            densesolver.cmatrixsolvem(ref a, n, ref b, m, (double)(AP.Math.RandomReal())>(double)(0.5), ref info, ref rep, ref x);
                            cerrors = cerrors | !cmatrixchecksingularm(n, m, info, ref rep, ref x);
                            
                            //
                            // Test CMatrixSolve()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            bv = new AP.Complex[n];
                            for(i_=0; i_<=n-1;i_++)
                            {
                                bv[i_] = b[i_,0];
                            }
                            densesolver.cmatrixsolve(ref a, n, ref bv, ref info, ref rep, ref xv);
                            cerrors = cerrors | !cmatrixchecksingular(n, info, ref rep, ref xv);
                            
                            //
                            // Test CMatrixLUSolveM()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            densesolver.cmatrixlusolvem(ref lua, ref p, n, ref b, m, ref info, ref rep, ref x);
                            cerrors = cerrors | !cmatrixchecksingularm(n, m, info, ref rep, ref x);
                            
                            //
                            // Test CMatrixLUSolve()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            bv = new AP.Complex[n];
                            for(i_=0; i_<=n-1;i_++)
                            {
                                bv[i_] = b[i_,0];
                            }
                            densesolver.cmatrixlusolve(ref lua, ref p, n, ref bv, ref info, ref rep, ref xv);
                            cerrors = cerrors | !cmatrixchecksingular(n, info, ref rep, ref xv);
                            
                            //
                            // Test CMatrixMixedSolveM()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            densesolver.cmatrixmixedsolvem(ref a, ref lua, ref p, n, ref b, m, ref info, ref rep, ref x);
                            cerrors = cerrors | !cmatrixchecksingularm(n, m, info, ref rep, ref x);
                            
                            //
                            // Test CMatrixMixedSolve()
                            //
                            info = 0;
                            unsetrep(ref rep);
                            cunset2d(ref x);
                            bv = new AP.Complex[n];
                            for(i_=0; i_<=n-1;i_++)
                            {
                                bv[i_] = b[i_,0];
                            }
                            densesolver.cmatrixmixedsolve(ref a, ref lua, ref p, n, ref bv, ref info, ref rep, ref xv);
                            cerrors = cerrors | !cmatrixchecksingular(n, info, ref rep, ref xv);
                        }
                    }
                }
            }
            
            //
            // test iterative improvement
            //
            for(pass=1; pass<=passcount; pass++)
            {
                
                //
                // Test iterative improvement matrices
                //
                // A matrix/right part are constructed such that both matrix
                // and solution components magnitudes are within (-1,+1).
                // Such matrix/right part have nice properties - system can
                // be solved using iterative improvement with |A*x-b| about
                // several ulps of max(1,|b|).
                //
                n = 100;
                a = new AP.Complex[n, n];
                b = new AP.Complex[n, 1];
                bv = new AP.Complex[n];
                tx = new double[2*n];
                xv = new AP.Complex[n];
                y = new AP.Complex[n];
                for(i=0; i<=n-1; i++)
                {
                    xv[i].x = 2*AP.Math.RandomReal()-1;
                    xv[i].y = 2*AP.Math.RandomReal()-1;
                }
                for(i=0; i<=n-1; i++)
                {
                    for(j=0; j<=n-1; j++)
                    {
                        a[i,j].x = 2*AP.Math.RandomReal()-1;
                        a[i,j].y = 2*AP.Math.RandomReal()-1;
                    }
                    for(i_=0; i_<=n-1;i_++)
                    {
                        y[i_] = a[i,i_];
                    }
                    xblas.xcdot(ref y, ref xv, n, ref tx, ref v, ref verr);
                    bv[i] = v;
                }
                for(i_=0; i_<=n-1;i_++)
                {
                    b[i_,0] = bv[i_];
                }
                
                //
                // Test CMatrixSolveM()
                //
                cunset2d(ref x);
                densesolver.cmatrixsolvem(ref a, n, ref b, 1, true, ref info, ref rep, ref x);
                if( info<=0 )
                {
                    rfserrors = true;
                }
                else
                {
                    xv = new AP.Complex[n];
                    for(i_=0; i_<=n-1;i_++)
                    {
                        xv[i_] = x[i_,0];
                    }
                    for(i=0; i<=n-1; i++)
                    {
                        for(i_=0; i_<=n-1;i_++)
                        {
                            y[i_] = a[i,i_];
                        }
                        xblas.xcdot(ref y, ref xv, n, ref tx, ref v, ref verr);
                        rfserrors = rfserrors | (double)(AP.Math.AbsComplex(v-b[i,0]))>(double)(8*AP.Math.MachineEpsilon*Math.Max(1, AP.Math.AbsComplex(b[i,0])));
                    }
                }
                
                //
                // Test CMatrixSolve()
                //
                cunset1d(ref xv);
                densesolver.cmatrixsolve(ref a, n, ref bv, ref info, ref rep, ref xv);
                if( info<=0 )
                {
                    rfserrors = true;
                }
                else
                {
                    for(i=0; i<=n-1; i++)
                    {
                        for(i_=0; i_<=n-1;i_++)
                        {
                            y[i_] = a[i,i_];
                        }
                        xblas.xcdot(ref y, ref xv, n, ref tx, ref v, ref verr);
                        rfserrors = rfserrors | (double)(AP.Math.AbsComplex(v-bv[i]))>(double)(8*AP.Math.MachineEpsilon*Math.Max(1, AP.Math.AbsComplex(bv[i])));
                    }
                }
                
                //
                // TODO: Test LS-solver on the same matrix
                //
            }
        }
예제 #44
0
        /*************************************************************************
        1-dimensional real FFT.

        Algorithm has O(N*logN) complexity for any N (composite or prime).

        INPUT PARAMETERS
            A   -   array[0..N-1] - real function to be transformed
            N   -   problem size

        OUTPUT PARAMETERS
            F   -   DFT of a input array, array[0..N-1]
                    F[j] = SUM(A[k]*exp(-2*pi*sqrt(-1)*j*k/N), k = 0..N-1)

        NOTE:
            F[] satisfies symmetry property F[k] = conj(F[N-k]),  so just one half
        of  array  is  usually needed. But for convinience subroutine returns full
        complex array (with frequencies above N/2), so its result may be  used  by
        other FFT-related subroutines.

          -- ALGLIB --
             Copyright 01.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fftr1d(ref double[] a,
            int n,
            ref AP.Complex[] f)
        {
            int i = 0;
            int n2 = 0;
            int idx = 0;
            AP.Complex hn = 0;
            AP.Complex hmnc = 0;
            AP.Complex v = 0;
            double[] buf = new double[0];
            ftbase.ftplan plan = new ftbase.ftplan();
            int i_ = 0;

            System.Diagnostics.Debug.Assert(n>0, "FFTR1D: incorrect N!");

            //
            // Special cases:
            // * N=1, FFT is just identity transform.
            // * N=2, FFT is simple too
            //
            // After this block we assume that N is strictly greater than 2
            //
            if( n==1 )
            {
                f = new AP.Complex[1];
                f[0] = a[0];
                return;
            }
            if( n==2 )
            {
                f = new AP.Complex[2];
                f[0].x = a[0]+a[1];
                f[0].y = 0;
                f[1].x = a[0]-a[1];
                f[1].y = 0;
                return;
            }

            //
            // Choose between odd-size and even-size FFTs
            //
            if( n%2==0 )
            {

                //
                // even-size real FFT, use reduction to the complex task
                //
                n2 = n/2;
                buf = new double[n];
                for(i_=0; i_<=n-1;i_++)
                {
                    buf[i_] = a[i_];
                }
                ftbase.ftbasegeneratecomplexfftplan(n2, ref plan);
                ftbase.ftbaseexecuteplan(ref buf, 0, n2, ref plan);
                f = new AP.Complex[n];
                for(i=0; i<=n2; i++)
                {
                    idx = 2*(i%n2);
                    hn.x = buf[idx+0];
                    hn.y = buf[idx+1];
                    idx = 2*((n2-i)%n2);
                    hmnc.x = buf[idx+0];
                    hmnc.y = -buf[idx+1];
                    v.x = -Math.Sin(-(2*Math.PI*i/n));
                    v.y = Math.Cos(-(2*Math.PI*i/n));
                    f[i] = hn+hmnc-v*(hn-hmnc);
                    f[i].x = 0.5*f[i].x;
                    f[i].y = 0.5*f[i].y;
                }
                for(i=n2+1; i<=n-1; i++)
                {
                    f[i] = AP.Math.Conj(f[n-i]);
                }
                return;
            }
            else
            {

                //
                // use complex FFT
                //
                f = new AP.Complex[n];
                for(i=0; i<=n-1; i++)
                {
                    f[i] = a[i];
                }
                fftc1d(ref f, n);
                return;
            }
        }
 /*************************************************************************
 Unsets real matrix
 *************************************************************************/
 private static void cunset2d(ref AP.Complex[,] x)
 {
     x = new AP.Complex[1, 1];
     x[0,0] = 2*AP.Math.RandomReal()-1;
 }
예제 #46
0
        /*************************************************************************
        1-dimensional real inverse FFT.

        Algorithm has O(N*logN) complexity for any N (composite or prime).

        INPUT PARAMETERS
            F   -   array[0..floor(N/2)] - frequencies from forward real FFT
            N   -   problem size

        OUTPUT PARAMETERS
            A   -   inverse DFT of a input array, array[0..N-1]

        NOTE:
            F[] should satisfy symmetry property F[k] = conj(F[N-k]), so just  one
        half of frequencies array is needed - elements from 0 to floor(N/2).  F[0]
        is ALWAYS real. If N is even F[floor(N/2)] is real too. If N is odd,  then
        F[floor(N/2)] has no special properties.

        Relying on properties noted above, FFTR1DInv subroutine uses only elements
        from 0th to floor(N/2)-th. It ignores imaginary part of F[0],  and in case
        N is even it ignores imaginary part of F[floor(N/2)] too.  So you can pass
        either frequencies array with N elements or reduced array with roughly N/2
        elements - subroutine will successfully transform both.

          -- ALGLIB --
             Copyright 01.06.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void fftr1dinv(ref AP.Complex[] f,
            int n,
            ref double[] a)
        {
            int i = 0;
            double[] h = new double[0];
            AP.Complex[] fh = new AP.Complex[0];

            System.Diagnostics.Debug.Assert(n>0, "FFTR1DInv: incorrect N!");

            //
            // Special case: N=1, FFT is just identity transform.
            // After this block we assume that N is strictly greater than 1.
            //
            if( n==1 )
            {
                a = new double[1];
                a[0] = f[0].x;
                return;
            }

            //
            // inverse real FFT is reduced to the inverse real FHT,
            // which is reduced to the forward real FHT,
            // which is reduced to the forward real FFT.
            //
            // Don't worry, it is really compact and efficient reduction :)
            //
            h = new double[n];
            a = new double[n];
            h[0] = f[0].x;
            for(i=1; i<=(int)Math.Floor((double)(n)/(double)(2))-1; i++)
            {
                h[i] = f[i].x-f[i].y;
                h[n-i] = f[i].x+f[i].y;
            }
            if( n%2==0 )
            {
                h[(int)Math.Floor((double)(n)/(double)(2))] = f[(int)Math.Floor((double)(n)/(double)(2))].x;
            }
            else
            {
                h[(int)Math.Floor((double)(n)/(double)(2))] = f[(int)Math.Floor((double)(n)/(double)(2))].x-f[(int)Math.Floor((double)(n)/(double)(2))].y;
                h[(int)Math.Floor((double)(n)/(double)(2))+1] = f[(int)Math.Floor((double)(n)/(double)(2))].x+f[(int)Math.Floor((double)(n)/(double)(2))].y;
            }
            fftr1d(ref h, n, ref fh);
            for(i=0; i<=n-1; i++)
            {
                a[i] = (fh[i].x-fh[i].y)/n;
            }
        }
        /*************************************************************************
        Checks whether solver results are correct solution.
        Returns True on success.
        *************************************************************************/
        private static bool cmatrixchecksolution(ref AP.Complex[,] xe,
            int n,
            double threshold,
            int info,
            ref densesolver.densesolverreport rep,
            ref AP.Complex[] xs)
        {
            bool result = new bool();
            AP.Complex[,] xsm = new AP.Complex[0,0];
            int i_ = 0;

            xsm = new AP.Complex[n, 1];
            for(i_=0; i_<=n-1;i_++)
            {
                xsm[i_,0] = xs[i_];
            }
            result = cmatrixchecksolutionm(ref xe, n, 1, threshold, info, ref rep, ref xsm);
            return result;
        }
예제 #48
0
        /*************************************************************************
        Subroutine for finding the eigenvalues and  eigenvectors  of  a  Hermitian
        matrix with given indexes by using bisection and inverse iteration methods

        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.
            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.
            IsUpperA -  storage format of matrix A.
            I1, I2 -    index interval for searching (from I1 to I2).
                        0 <= I1 <= I2 <= N-1.

        Output parameters:
            W       -   array of the eigenvalues found.
                        Array whose index ranges within [0..I2-I1].
            Z       -   if ZNeeded is equal to:
                         * 0, Z hasn’t changed;
                         * 1, Z contains eigenvectors.
                        Array whose indexes range within [0..N-1, 0..I2-I1].
                        In  that  case,  the eigenvectors are stored in the matrix
                        columns.

        Result:
            True, if successful. W contains the eigenvalues, Z contains the
            eigenvectors (if needed).

            False, if the bisection method subroutine  wasn't  able  to  find  the
            eigenvalues  in  the  given  interval  or  if  the  inverse  iteration
            subroutine wasn't able to find  all  the  corresponding  eigenvectors.
            In that case, the eigenvalues and eigenvectors are not returned.

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

          -- ALGLIB --
             Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey.
        *************************************************************************/
        public static bool hmatrixevdi(AP.Complex[,] a,
            int n,
            int zneeded,
            bool isupper,
            int i1,
            int i2,
            ref double[] w,
            ref AP.Complex[,] z)
        {
            bool result = new bool();
            AP.Complex[,] q = new AP.Complex[0,0];
            double[,] t = new double[0,0];
            AP.Complex[] tau = new AP.Complex[0];
            double[] e = new double[0];
            double[] work = new double[0];
            int i = 0;
            int k = 0;
            double v = 0;
            int m = 0;
            int i_ = 0;

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

            System.Diagnostics.Debug.Assert(zneeded==0 | zneeded==1, "HermitianEigenValuesAndVectorsByIndexes: incorrect ZNeeded");
            
            //
            // Reduce to tridiagonal form
            //
            ortfac.hmatrixtd(ref a, n, isupper, ref tau, ref w, ref e);
            if( zneeded==1 )
            {
                ortfac.hmatrixtdunpackq(ref a, n, isupper, ref tau, ref q);
                zneeded = 2;
            }
            
            //
            // Bisection and inverse iteration
            //
            result = smatrixtdevdi(ref w, ref e, n, zneeded, i1, i2, ref t);
            
            //
            // Eigenvectors are needed
            // Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T
            //
            m = i2-i1+1;
            if( result & zneeded!=0 )
            {
                work = new double[m-1+1];
                z = new AP.Complex[n-1+1, m-1+1];
                for(i=0; i<=n-1; i++)
                {
                    
                    //
                    // Calculate real part
                    //
                    for(k=0; k<=m-1; k++)
                    {
                        work[k] = 0;
                    }
                    for(k=0; k<=n-1; k++)
                    {
                        v = q[i,k].x;
                        for(i_=0; i_<=m-1;i_++)
                        {
                            work[i_] = work[i_] + v*t[k,i_];
                        }
                    }
                    for(k=0; k<=m-1; k++)
                    {
                        z[i,k].x = work[k];
                    }
                    
                    //
                    // Calculate imaginary part
                    //
                    for(k=0; k<=m-1; k++)
                    {
                        work[k] = 0;
                    }
                    for(k=0; k<=n-1; k++)
                    {
                        v = q[i,k].y;
                        for(i_=0; i_<=m-1;i_++)
                        {
                            work[i_] = work[i_] + v*t[k,i_];
                        }
                    }
                    for(k=0; k<=m-1; k++)
                    {
                        z[i,k].y = work[k];
                    }
                }
            }
            return result;
        }
        /*************************************************************************
        Copy
        *************************************************************************/
        private static void cmatrixmakeacopy(ref AP.Complex[,] a,
            int m,
            int n,
            ref AP.Complex[,] b)
        {
            int i = 0;
            int j = 0;

            b = new AP.Complex[m-1+1, n-1+1];
            for(i=0; i<=m-1; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    b[i,j] = a[i,j];
                }
            }
        }
예제 #50
0
        /*************************************************************************
        *  More precise complex dot-product. Absolute error of  subroutine  result is
        *  about 1 ulp of max(MX,V), where:
        *   MX = max( |a[i]*b[i]| )
        *   V  = |(a,b)|
        *
        *  INPUT PARAMETERS
        *   A       -   array[0..N-1], vector 1
        *   B       -   array[0..N-1], vector 2
        *   N       -   vectors length, N<2^29.
        *   Temp    -   array[0..2*N-1], pre-allocated temporary storage
        *
        *  OUTPUT PARAMETERS
        *   R       -   (A,B)
        *   RErr    -   estimate of error. This estimate accounts for both  errors
        *               during  calculation  of  (A,B)  and  errors  introduced by
        *               rounding of A and B to fit in double (about 1 ulp).
        *
        *  -- ALGLIB --
        *    Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void xcdot(ref AP.Complex[] a,
                                 ref AP.Complex[] b,
                                 int n,
                                 ref double[] temp,
                                 ref AP.Complex r,
                                 ref double rerr)
        {
            int    i     = 0;
            double mx    = 0;
            double v     = 0;
            double rerrx = 0;
            double rerry = 0;


            //
            // special cases:
            // * N=0
            //
            if (n == 0)
            {
                r    = 0;
                rerr = 0;
                return;
            }

            //
            // calculate real part
            //
            mx = 0;
            for (i = 0; i <= n - 1; i++)
            {
                v = a[i].x * b[i].x;
                temp[2 * i + 0] = v;
                mx = Math.Max(mx, Math.Abs(v));
                v  = -(a[i].y * b[i].y);
                temp[2 * i + 1] = v;
                mx = Math.Max(mx, Math.Abs(v));
            }
            if ((double)(mx) == (double)(0))
            {
                r.x   = 0;
                rerrx = 0;
            }
            else
            {
                xsum(ref temp, mx, 2 * n, ref r.x, ref rerrx);
            }

            //
            // calculate imaginary part
            //
            mx = 0;
            for (i = 0; i <= n - 1; i++)
            {
                v = a[i].x * b[i].y;
                temp[2 * i + 0] = v;
                mx = Math.Max(mx, Math.Abs(v));
                v  = a[i].y * b[i].x;
                temp[2 * i + 1] = v;
                mx = Math.Max(mx, Math.Abs(v));
            }
            if ((double)(mx) == (double)(0))
            {
                r.y   = 0;
                rerry = 0;
            }
            else
            {
                xsum(ref temp, mx, 2 * n, ref r.y, ref rerry);
            }

            //
            // total error
            //
            if ((double)(rerrx) == (double)(0) & (double)(rerry) == (double)(0))
            {
                rerr = 0;
            }
            else
            {
                rerr = Math.Max(rerrx, rerry) * Math.Sqrt(1 + AP.Math.Sqr(Math.Min(rerrx, rerry) / Math.Max(rerrx, rerry)));
            }
        }
예제 #51
0
        /*************************************************************************
        Internal real FFT stub.
        Uses straightforward formula with O(N^2) complexity.
        *************************************************************************/
        private static void refinternalrfft(ref double[] a,
            int nn,
            ref AP.Complex[] f)
        {
            double[] tmp = new double[0];
            int i = 0;

            tmp = new double[2*nn-1+1];
            for(i=0; i<=nn-1; i++)
            {
                tmp[2*i] = a[i];
                tmp[2*i+1] = 0;
            }
            refinternalcfft(ref tmp, nn, false);
            f = new AP.Complex[nn];
            for(i=0; i<=nn-1; i++)
            {
                f[i].x = tmp[2*i+0];
                f[i].y = tmp[2*i+1];
            }
        }
예제 #52
0
        /*************************************************************************
        *  Real implementation of CMatrixScaledTRSafeSolve
        *
        *  -- ALGLIB routine --
        *    21.01.2010
        *    Bochkanov Sergey
        *************************************************************************/
        public static bool rmatrixscaledtrsafesolve(ref double[,] a,
                                                    double sa,
                                                    int n,
                                                    ref double[] 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;
            double     vr    = 0;

            AP.Complex cx  = 0;
            double[]   tmp = new double[0];
            int        i_  = 0;

            System.Diagnostics.Debug.Assert(n > 0, "RMatrixTRSafeSolve: incorrect N!");
            System.Diagnostics.Debug.Assert(trans == 0 | trans == 1, "RMatrixTRSafeSolve: 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, Math.Abs(x[i]));
            }
            nrmx = 0;

            //
            // Solve
            //
            tmp    = new double[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_];
                        }
                        vr = 0.0;
                        for (i_ = i + 1; i_ <= n - 1; i_++)
                        {
                            vr += tmp[i_] * x[i_];
                        }
                        beta = x[i] - vr;
                    }
                    else
                    {
                        beta = x[i];
                    }

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref cx);
                    if (!result)
                    {
                        return(result);
                    }
                    x[i] = cx.x;
                }
                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_];
                        }
                        vr = 0.0;
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            vr += tmp[i_] * x[i_];
                        }
                        beta = x[i] - vr;
                    }
                    else
                    {
                        beta = x[i];
                    }

                    //
                    // solve alpha*x[i] = beta
                    //
                    result = cbasicsolveandupdate(alpha, beta, lnmax, nrmb, maxgrowth, ref nrmx, ref cx);
                    if (!result)
                    {
                        return(result);
                    }
                    x[i] = cx.x;
                }
                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 cx);
                    if (!result)
                    {
                        return(result);
                    }
                    x[i] = cx.x;

                    //
                    // update the rest of right part
                    //
                    if (i < n - 1)
                    {
                        vr = cx.x;
                        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_] - vr * 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 cx);
                    if (!result)
                    {
                        return(result);
                    }
                    x[i] = cx.x;

                    //
                    // update the rest of right part
                    //
                    if (i > 0)
                    {
                        vr = cx.x;
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            tmp[i_] = sa * a[i, i_];
                        }
                        for (i_ = 0; i_ <= i - 1; i_++)
                        {
                            x[i_] = x[i_] - vr * tmp[i_];
                        }
                    }
                }
                return(result);
            }
            result = false;
            return(result);
        }
예제 #53
0
        public static bool testtrfac(bool silent)
        {
            bool result = new bool();

            double[,] ra      = new double[0, 0];
            double[,] ral     = new double[0, 0];
            double[,] rau     = new double[0, 0];
            AP.Complex[,] ca  = new AP.Complex[0, 0];
            AP.Complex[,] cal = new AP.Complex[0, 0];
            AP.Complex[,] cau = new AP.Complex[0, 0];
            int m     = 0;
            int n     = 0;
            int mx    = 0;
            int maxmn = 0;
            int i     = 0;
            int j     = 0;
            int minij = 0;
            int pass  = 0;

            AP.Complex vc        = 0;
            double     vr        = 0;
            bool       waserrors = new bool();
            bool       spderr    = new bool();
            bool       hpderr    = new bool();
            bool       rerr      = new bool();
            bool       cerr      = new bool();
            bool       properr   = new bool();
            double     threshold = 0;
            int        i_        = 0;

            rerr      = false;
            spderr    = false;
            cerr      = false;
            hpderr    = false;
            properr   = false;
            waserrors = false;
            maxmn     = 4 * ablas.ablasblocksize(ref ra) + 1;
            threshold = 1000 * AP.Math.MachineEpsilon * maxmn;

            //
            // test LU
            //
            for (mx = 1; mx <= maxmn; mx++)
            {
                //
                // Initialize N/M, both are <=MX,
                // at least one of them is exactly equal to MX
                //
                n = 1 + AP.Math.RandomInteger(mx);
                m = 1 + AP.Math.RandomInteger(mx);
                if ((double)(AP.Math.RandomReal()) > (double)(0.5))
                {
                    n = mx;
                }
                else
                {
                    m = mx;
                }

                //
                // First, test on zero matrix
                //
                ra = new double[m, n];
                ca = new AP.Complex[m, n];
                for (i = 0; i <= m - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        ra[i, j] = 0;
                        ca[i, j] = 0;
                    }
                }
                testcluproblem(ref ca, m, n, threshold, ref cerr, ref properr);
                testrluproblem(ref ra, m, n, threshold, ref rerr, ref properr);

                //
                // Second, random matrix with moderate condition number
                //
                ra = new double[m, n];
                ca = new AP.Complex[m, n];
                for (i = 0; i <= m - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        ra[i, j] = 0;
                        ca[i, j] = 0;
                    }
                }
                for (i = 0; i <= Math.Min(m, n) - 1; i++)
                {
                    ra[i, i] = 1 + 10 * AP.Math.RandomReal();
                    ca[i, i] = 1 + 10 * AP.Math.RandomReal();
                }
                matgen.cmatrixrndorthogonalfromtheleft(ref ca, m, n);
                matgen.cmatrixrndorthogonalfromtheright(ref ca, m, n);
                matgen.rmatrixrndorthogonalfromtheleft(ref ra, m, n);
                matgen.rmatrixrndorthogonalfromtheright(ref ra, m, n);
                testcluproblem(ref ca, m, n, threshold, ref cerr, ref properr);
                testrluproblem(ref ra, m, n, threshold, ref rerr, ref properr);
            }

            //
            // Test Cholesky
            //
            for (n = 1; n <= maxmn; n++)
            {
                //
                // Load CA (HPD matrix with low condition number),
                //      CAL and CAU - its lower and upper triangles
                //
                matgen.hpdmatrixrndcond(n, 1 + 50 * AP.Math.RandomReal(), ref ca);
                cal = new AP.Complex[n, n];
                cau = new AP.Complex[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        cal[i, j] = i;
                        cau[i, j] = j;
                    }
                }
                for (i = 0; i <= n - 1; i++)
                {
                    for (i_ = 0; i_ <= i; i_++)
                    {
                        cal[i, i_] = ca[i, i_];
                    }
                    for (i_ = i; i_ <= n - 1; i_++)
                    {
                        cau[i, i_] = ca[i, i_];
                    }
                }

                //
                // Test HPDMatrixCholesky:
                // 1. it must leave upper (lower) part unchanged
                // 2. max(A-L*L^H) must be small
                //
                if (trfac.hpdmatrixcholesky(ref cal, n, false))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = 0; j <= n - 1; j++)
                        {
                            if (j > i)
                            {
                                hpderr = hpderr | cal[i, j] != i;
                            }
                            else
                            {
                                vc = 0.0;
                                for (i_ = 0; i_ <= j; i_++)
                                {
                                    vc += cal[i, i_] * AP.Math.Conj(cal[j, i_]);
                                }
                                hpderr = hpderr | (double)(AP.Math.AbsComplex(ca[i, j] - vc)) > (double)(threshold);
                            }
                        }
                    }
                }
                else
                {
                    hpderr = true;
                }
                if (trfac.hpdmatrixcholesky(ref cau, n, true))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = 0; j <= n - 1; j++)
                        {
                            if (j < i)
                            {
                                hpderr = hpderr | cau[i, j] != j;
                            }
                            else
                            {
                                vc = 0.0;
                                for (i_ = 0; i_ <= i; i_++)
                                {
                                    vc += AP.Math.Conj(cau[i_, i]) * cau[i_, j];
                                }
                                hpderr = hpderr | (double)(AP.Math.AbsComplex(ca[i, j] - vc)) > (double)(threshold);
                            }
                        }
                    }
                }
                else
                {
                    hpderr = true;
                }

                //
                // Load RA (SPD matrix with low condition number),
                //      RAL and RAU - its lower and upper triangles
                //
                matgen.spdmatrixrndcond(n, 1 + 50 * AP.Math.RandomReal(), ref ra);
                ral = new double[n, n];
                rau = new double[n, n];
                for (i = 0; i <= n - 1; i++)
                {
                    for (j = 0; j <= n - 1; j++)
                    {
                        ral[i, j] = i;
                        rau[i, j] = j;
                    }
                }
                for (i = 0; i <= n - 1; i++)
                {
                    for (i_ = 0; i_ <= i; i_++)
                    {
                        ral[i, i_] = ra[i, i_];
                    }
                    for (i_ = i; i_ <= n - 1; i_++)
                    {
                        rau[i, i_] = ra[i, i_];
                    }
                }

                //
                // Test SPDMatrixCholesky:
                // 1. it must leave upper (lower) part unchanged
                // 2. max(A-L*L^H) must be small
                //
                if (trfac.spdmatrixcholesky(ref ral, n, false))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = 0; j <= n - 1; j++)
                        {
                            if (j > i)
                            {
                                spderr = spderr | (double)(ral[i, j]) != (double)(i);
                            }
                            else
                            {
                                vr = 0.0;
                                for (i_ = 0; i_ <= j; i_++)
                                {
                                    vr += ral[i, i_] * ral[j, i_];
                                }
                                spderr = spderr | (double)(Math.Abs(ra[i, j] - vr)) > (double)(threshold);
                            }
                        }
                    }
                }
                else
                {
                    spderr = true;
                }
                if (trfac.spdmatrixcholesky(ref rau, n, true))
                {
                    for (i = 0; i <= n - 1; i++)
                    {
                        for (j = 0; j <= n - 1; j++)
                        {
                            if (j < i)
                            {
                                spderr = spderr | (double)(rau[i, j]) != (double)(j);
                            }
                            else
                            {
                                vr = 0.0;
                                for (i_ = 0; i_ <= i; i_++)
                                {
                                    vr += rau[i_, i] * rau[i_, j];
                                }
                                spderr = spderr | (double)(Math.Abs(ra[i, j] - vr)) > (double)(threshold);
                            }
                        }
                    }
                }
                else
                {
                    spderr = true;
                }
            }

            //
            // report
            //
            waserrors = rerr | spderr | cerr | hpderr | properr;
            if (!silent)
            {
                System.Console.Write("TESTING TRIANGULAR FACTORIZATIONS");
                System.Console.WriteLine();
                System.Console.Write("* REAL:                                  ");
                if (rerr)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* SPD:                                   ");
                if (spderr)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* COMPLEX:                               ");
                if (cerr)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* HPD:                                   ");
                if (hpderr)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* OTHER PROPERTIES:                      ");
                if (properr)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                if (waserrors)
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
                System.Console.WriteLine();
            }
            result = !waserrors;
            return(result);
        }
예제 #54
0
        /*************************************************************************
        *  Test
        *************************************************************************/
        public static bool testfft(bool silent)
        {
            bool result = new bool();
            int  n      = 0;
            int  i      = 0;
            int  k      = 0;

            AP.Complex[]  a1          = new AP.Complex[0];
            AP.Complex[]  a2          = new AP.Complex[0];
            AP.Complex[]  a3          = new AP.Complex[0];
            double[]      r1          = new double[0];
            double[]      r2          = new double[0];
            double[]      buf         = new double[0];
            ftbase.ftplan plan        = new ftbase.ftplan();
            int           maxn        = 0;
            double        bidierr     = 0;
            double        bidirerr    = 0;
            double        referr      = 0;
            double        refrerr     = 0;
            double        reinterr    = 0;
            double        errtol      = 0;
            bool          referrors   = new bool();
            bool          bidierrors  = new bool();
            bool          refrerrors  = new bool();
            bool          bidirerrors = new bool();
            bool          reinterrors = new bool();
            bool          waserrors   = new bool();
            int           i_          = 0;

            maxn        = 128;
            errtol      = 100000 * Math.Pow(maxn, (double)(3) / (double)(2)) * AP.Math.MachineEpsilon;
            bidierrors  = false;
            referrors   = false;
            bidirerrors = false;
            refrerrors  = false;
            reinterrors = false;
            waserrors   = false;

            //
            // Test bi-directional error: norm(x-invFFT(FFT(x)))
            //
            bidierr  = 0;
            bidirerr = 0;
            for (n = 1; n <= maxn; n++)
            {
                //
                // Complex FFT/invFFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                a3 = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    a1[i].x = 2 * AP.Math.RandomReal() - 1;
                    a1[i].y = 2 * AP.Math.RandomReal() - 1;
                    a2[i]   = a1[i];
                    a3[i]   = a1[i];
                }
                fft.fftc1d(ref a2, n);
                fft.fftc1dinv(ref a2, n);
                fft.fftc1dinv(ref a3, n);
                fft.fftc1d(ref a3, n);
                for (i = 0; i <= n - 1; i++)
                {
                    bidierr = Math.Max(bidierr, AP.Math.AbsComplex(a1[i] - a2[i]));
                    bidierr = Math.Max(bidierr, AP.Math.AbsComplex(a1[i] - a3[i]));
                }

                //
                // Real
                //
                r1 = new double[n];
                r2 = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    r1[i] = 2 * AP.Math.RandomReal() - 1;
                    r2[i] = r1[i];
                }
                fft.fftr1d(ref r2, n, ref a1);
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    r2[i_] = 0 * r2[i_];
                }
                fft.fftr1dinv(ref a1, n, ref r2);
                for (i = 0; i <= n - 1; i++)
                {
                    bidirerr = Math.Max(bidirerr, AP.Math.AbsComplex(r1[i] - r2[i]));
                }
            }
            bidierrors  = bidierrors | (double)(bidierr) > (double)(errtol);
            bidirerrors = bidirerrors | (double)(bidirerr) > (double)(errtol);

            //
            // Test against reference O(N^2) implementation
            //
            referr  = 0;
            refrerr = 0;
            for (n = 1; n <= maxn; n++)
            {
                //
                // Complex FFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    a1[i].x = 2 * AP.Math.RandomReal() - 1;
                    a1[i].y = 2 * AP.Math.RandomReal() - 1;
                    a2[i]   = a1[i];
                }
                fft.fftc1d(ref a1, n);
                reffftc1d(ref a2, n);
                for (i = 0; i <= n - 1; i++)
                {
                    referr = Math.Max(referr, AP.Math.AbsComplex(a1[i] - a2[i]));
                }

                //
                // Complex inverse FFT
                //
                a1 = new AP.Complex[n];
                a2 = new AP.Complex[n];
                for (i = 0; i <= n - 1; i++)
                {
                    a1[i].x = 2 * AP.Math.RandomReal() - 1;
                    a1[i].y = 2 * AP.Math.RandomReal() - 1;
                    a2[i]   = a1[i];
                }
                fft.fftc1dinv(ref a1, n);
                reffftc1dinv(ref a2, n);
                for (i = 0; i <= n - 1; i++)
                {
                    referr = Math.Max(referr, AP.Math.AbsComplex(a1[i] - a2[i]));
                }

                //
                // Real forward/inverse FFT:
                // * calculate and check forward FFT
                // * use precalculated FFT to check backward FFT
                //   fill unused parts of frequencies array with random numbers
                //   to ensure that they are not really used
                //
                r1 = new double[n];
                r2 = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    r1[i] = 2 * AP.Math.RandomReal() - 1;
                    r2[i] = r1[i];
                }
                fft.fftr1d(ref r1, n, ref a1);
                refinternalrfft(ref r2, n, ref a2);
                for (i = 0; i <= n - 1; i++)
                {
                    refrerr = Math.Max(refrerr, AP.Math.AbsComplex(a1[i] - a2[i]));
                }
                a3 = new AP.Complex[(int)Math.Floor((double)(n) / (double)(2)) + 1];
                for (i = 0; i <= (int)Math.Floor((double)(n) / (double)(2)); i++)
                {
                    a3[i] = a2[i];
                }
                a3[0].y = 2 * AP.Math.RandomReal() - 1;
                if (n % 2 == 0)
                {
                    a3[(int)Math.Floor((double)(n) / (double)(2))].y = 2 * AP.Math.RandomReal() - 1;
                }
                for (i = 0; i <= n - 1; i++)
                {
                    r1[i] = 0;
                }
                fft.fftr1dinv(ref a3, n, ref r1);
                for (i = 0; i <= n - 1; i++)
                {
                    refrerr = Math.Max(refrerr, Math.Abs(r2[i] - r1[i]));
                }
            }
            referrors  = referrors | (double)(referr) > (double)(errtol);
            refrerrors = refrerrors | (double)(refrerr) > (double)(errtol);

            //
            // test internal real even FFT
            //
            reinterr = 0;
            for (k = 1; k <= maxn / 2; k++)
            {
                n = 2 * k;

                //
                // Real forward FFT
                //
                r1 = new double[n];
                r2 = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    r1[i] = 2 * AP.Math.RandomReal() - 1;
                    r2[i] = r1[i];
                }
                ftbase.ftbasegeneratecomplexfftplan(n / 2, ref plan);
                buf = new double[n];
                fft.fftr1dinternaleven(ref r1, n, ref buf, ref plan);
                refinternalrfft(ref r2, n, ref a2);
                reinterr = Math.Max(reinterr, Math.Abs(r1[0] - a2[0].x));
                reinterr = Math.Max(reinterr, Math.Abs(r1[1] - a2[n / 2].x));
                for (i = 1; i <= n / 2 - 1; i++)
                {
                    reinterr = Math.Max(reinterr, Math.Abs(r1[2 * i + 0] - a2[i].x));
                    reinterr = Math.Max(reinterr, Math.Abs(r1[2 * i + 1] - a2[i].y));
                }

                //
                // Real backward FFT
                //
                r1 = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    r1[i] = 2 * AP.Math.RandomReal() - 1;
                }
                a2    = new AP.Complex[(int)Math.Floor((double)(n) / (double)(2)) + 1];
                a2[0] = r1[0];
                for (i = 1; i <= (int)Math.Floor((double)(n) / (double)(2)) - 1; i++)
                {
                    a2[i].x = r1[2 * i + 0];
                    a2[i].y = r1[2 * i + 1];
                }
                a2[(int)Math.Floor((double)(n) / (double)(2))] = r1[1];
                ftbase.ftbasegeneratecomplexfftplan(n / 2, ref plan);
                buf = new double[n];
                fft.fftr1dinvinternaleven(ref r1, n, ref buf, ref plan);
                fft.fftr1dinv(ref a2, n, ref r2);
                for (i = 0; i <= n - 1; i++)
                {
                    reinterr = Math.Max(reinterr, Math.Abs(r1[i] - r2[i]));
                }
            }
            reinterrors = reinterrors | (double)(reinterr) > (double)(errtol);

            //
            // end
            //
            waserrors = bidierrors | bidirerrors | referrors | refrerrors | reinterrors;
            if (!silent)
            {
                System.Console.Write("TESTING FFT");
                System.Console.WriteLine();
                System.Console.Write("FINAL RESULT:                             ");
                if (waserrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* BI-DIRECTIONAL COMPLEX TEST:            ");
                if (bidierrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE COMPLEX FFT:          ");
                if (referrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* BI-DIRECTIONAL REAL TEST:               ");
                if (bidirerrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* AGAINST REFERENCE REAL FFT:             ");
                if (refrerrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("* INTERNAL EVEN FFT:                      ");
                if (reinterrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                if (waserrors)
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
            }
            result = !waserrors;
            return(result);
        }
예제 #55
0
        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_];
                    }
                }
            }
        }
예제 #56
0
        /*************************************************************************
        *  Generation of an elementary complex reflection transformation
        *
        *  The subroutine generates elementary complex reflection H of  order  N,  so
        *  that, for a given X, the following equality holds true:
        *
        *    ( X(1) )   ( Beta )
        *  H' * (  ..  ) = (  0   ),   H'*H = I,   Beta is a real number
        *    ( X(n) )   (  0   )
        *
        *  where
        *
        *             ( V(1) )
        *  H = 1 - Tau * (  ..  ) * ( conj(V(1)), ..., conj(V(n)) )
        *             ( V(n) )
        *
        *  where the first component of vector V equals 1.
        *
        *  Input parameters:
        *   X   -   vector. Array with elements [1..N].
        *   N   -   reflection order.
        *
        *  Output parameters:
        *   X   -   components from 2 to N are replaced by vector V.
        *           The first component is replaced with parameter Beta.
        *   Tau -   scalar value Tau.
        *
        *  This subroutine is the modification of CLARFG subroutines  from the LAPACK
        *  library. It has similar functionality except for the fact that it  doesn’t
        *  handle errors when intermediate results cause an overflow.
        *
        *  -- LAPACK auxiliary 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 complexgeneratereflection(ref AP.Complex[] x,
                                                     int n,
                                                     ref AP.Complex tau)
        {
            int j = 0;

            AP.Complex alpha = 0;
            double     alphi = 0;
            double     alphr = 0;
            double     beta  = 0;
            double     xnorm = 0;
            double     mx    = 0;

            AP.Complex t = 0;
            double     s = 0;

            AP.Complex v  = 0;
            int        i_ = 0;

            if (n <= 0)
            {
                tau = 0;
                return;
            }

            //
            // Scale if needed (to avoid overflow/underflow during intermediate
            // calculations).
            //
            mx = 0;
            for (j = 1; j <= n; j++)
            {
                mx = Math.Max(AP.Math.AbsComplex(x[j]), mx);
            }
            s = 1;
            if ((double)(mx) != (double)(0))
            {
                if ((double)(mx) < (double)(1))
                {
                    s = Math.Sqrt(AP.Math.MinRealNumber);
                    v = 1 / s;
                    for (i_ = 1; i_ <= n; i_++)
                    {
                        x[i_] = v * x[i_];
                    }
                }
                else
                {
                    s = Math.Sqrt(AP.Math.MaxRealNumber);
                    v = 1 / s;
                    for (i_ = 1; i_ <= n; i_++)
                    {
                        x[i_] = v * x[i_];
                    }
                }
            }

            //
            // calculate
            //
            alpha = x[1];
            mx    = 0;
            for (j = 2; j <= n; j++)
            {
                mx = Math.Max(AP.Math.AbsComplex(x[j]), mx);
            }
            xnorm = 0;
            if ((double)(mx) != (double)(0))
            {
                for (j = 2; j <= n; j++)
                {
                    t     = x[j] / mx;
                    xnorm = xnorm + (t * AP.Math.Conj(t)).x;
                }
                xnorm = Math.Sqrt(xnorm) * mx;
            }
            alphr = alpha.x;
            alphi = alpha.y;
            if ((double)(xnorm) == (double)(0) & (double)(alphi) == (double)(0))
            {
                tau  = 0;
                x[1] = x[1] * s;
                return;
            }
            mx   = Math.Max(Math.Abs(alphr), Math.Abs(alphi));
            mx   = Math.Max(mx, Math.Abs(xnorm));
            beta = -(mx * Math.Sqrt(AP.Math.Sqr(alphr / mx) + AP.Math.Sqr(alphi / mx) + AP.Math.Sqr(xnorm / mx)));
            if ((double)(alphr) < (double)(0))
            {
                beta = -beta;
            }
            tau.x = (beta - alphr) / beta;
            tau.y = -(alphi / beta);
            alpha = 1 / (alpha - beta);
            if (n > 1)
            {
                for (i_ = 2; i_ <= n; i_++)
                {
                    x[i_] = alpha * x[i_];
                }
            }
            alpha = beta;
            x[1]  = alpha;

            //
            // Scale back
            //
            x[1] = x[1] * s;
        }
예제 #57
0
        /*************************************************************************
        Internal Cholesky solver

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        private static void hpdmatrixcholeskysolveinternal(ref AP.Complex[,] cha,
            double sqrtscalea,
            int n,
            bool isupper,
            ref AP.Complex[,] a,
            bool havea,
            ref AP.Complex[,] b,
            int m,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            int i = 0;
            int j = 0;
            int k = 0;
            int rfs = 0;
            int nrfs = 0;
            AP.Complex[] xc = new AP.Complex[0];
            AP.Complex[] y = new AP.Complex[0];
            AP.Complex[] bc = new AP.Complex[0];
            AP.Complex[] xa = new AP.Complex[0];
            AP.Complex[] xb = new AP.Complex[0];
            AP.Complex[] tx = new AP.Complex[0];
            double v = 0;
            double verr = 0;
            double mxb = 0;
            double scaleright = 0;
            bool smallerr = new bool();
            bool terminatenexttime = new bool();
            int i_ = 0;

            System.Diagnostics.Debug.Assert((double)(sqrtscalea)>(double)(0));
            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            x = new AP.Complex[n, m];
            y = new AP.Complex[n];
            xc = new AP.Complex[n];
            bc = new AP.Complex[n];
            tx = new AP.Complex[n+1];
            xa = new AP.Complex[n+1];
            xb = new AP.Complex[n+1];
            
            //
            // estimate condition number, test for near singularity
            //
            rep.r1 = rcond.hpdmatrixcholeskyrcond(ref cha, n, isupper);
            rep.rinf = rep.r1;
            if( (double)(rep.r1)<(double)(rcond.rcondthreshold()) )
            {
                for(i=0; i<=n-1; i++)
                {
                    for(j=0; j<=m-1; j++)
                    {
                        x[i,j] = 0;
                    }
                }
                rep.r1 = 0;
                rep.rinf = 0;
                info = -3;
                return;
            }
            info = 1;
            
            //
            // solve
            //
            for(k=0; k<=m-1; k++)
            {
                
                //
                // copy B to contiguous storage
                //
                for(i_=0; i_<=n-1;i_++)
                {
                    bc[i_] = b[i_,k];
                }
                
                //
                // Scale right part:
                // * MX stores max(|Bi|)
                // * ScaleRight stores actual scaling applied to B when solving systems
                //   it is chosen to make |scaleRight*b| close to 1.
                //
                mxb = 0;
                for(i=0; i<=n-1; i++)
                {
                    mxb = Math.Max(mxb, AP.Math.AbsComplex(bc[i]));
                }
                if( (double)(mxb)==(double)(0) )
                {
                    mxb = 1;
                }
                scaleright = 1/mxb;
                
                //
                // First, non-iterative part of solution process.
                // We use separate code for this task because
                // XDot is quite slow and we want to save time.
                //
                for(i_=0; i_<=n-1;i_++)
                {
                    xc[i_] = scaleright*bc[i_];
                }
                hpdbasiccholeskysolve(ref cha, sqrtscalea, n, isupper, ref xc, ref tx);
                
                //
                // Store xc.
                // Post-scale result.
                //
                v = AP.Math.Sqr(sqrtscalea)*mxb;
                for(i_=0; i_<=n-1;i_++)
                {
                    x[i_,k] = v*xc[i_];
                }
            }
        }
예제 #58
0
        /*************************************************************************
        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;
            }
        }
예제 #59
0
 /*************************************************************************
 *  Unsets 2D array.
 *************************************************************************/
 private static void unset2d(ref AP.Complex[,] a)
 {
     a       = new AP.Complex[0 + 1, 0 + 1];
     a[0, 0] = 2 * AP.Math.RandomReal() - 1;
 }
예제 #60
0
        /*************************************************************************
        Dense solver. Same as RMatrixSolveM(), but for complex matrices.

        Algorithm features:
        * automatic detection of degenerate cases
        * condition number estimation
        * iterative refinement
        * O(N^3+M*N^2) complexity

        INPUT PARAMETERS
            A       -   array[0..N-1,0..N-1], system matrix
            N       -   size of A
            B       -   array[0..N-1,0..M-1], right part
            M       -   right part size
            RFS     -   iterative refinement switch:
                        * True - refinement is used.
                          Less performance, more precision.
                        * False - refinement is not used.
                          More performance, less precision.

        OUTPUT PARAMETERS
            Info    -   same as in RMatrixSolve
            Rep     -   same as in RMatrixSolve
            X       -   same as in RMatrixSolve

          -- ALGLIB --
             Copyright 27.01.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void cmatrixsolvem(ref AP.Complex[,] a,
            int n,
            ref AP.Complex[,] b,
            int m,
            bool rfs,
            ref int info,
            ref densesolverreport rep,
            ref AP.Complex[,] x)
        {
            AP.Complex[,] da = new AP.Complex[0,0];
            AP.Complex[,] emptya = new AP.Complex[0,0];
            int[] p = new int[0];
            double scalea = 0;
            int i = 0;
            int j = 0;
            int i_ = 0;

            
            //
            // prepare: check inputs, allocate space...
            //
            if( n<=0 | m<=0 )
            {
                info = -1;
                return;
            }
            da = new AP.Complex[n, n];
            
            //
            // 1. scale matrix, max(|A[i,j]|)
            // 2. factorize scaled matrix
            // 3. solve
            //
            scalea = 0;
            for(i=0; i<=n-1; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    scalea = Math.Max(scalea, AP.Math.AbsComplex(a[i,j]));
                }
            }
            if( (double)(scalea)==(double)(0) )
            {
                scalea = 1;
            }
            scalea = 1/scalea;
            for(i=0; i<=n-1; i++)
            {
                for(i_=0; i_<=n-1;i_++)
                {
                    da[i,i_] = a[i,i_];
                }
            }
            trfac.cmatrixlu(ref da, n, n, ref p);
            if( rfs )
            {
                cmatrixlusolveinternal(ref da, ref p, scalea, n, ref a, true, ref b, m, ref info, ref rep, ref x);
            }
            else
            {
                cmatrixlusolveinternal(ref da, ref p, scalea, n, ref emptya, false, ref b, m, ref info, ref rep, ref x);
            }
        }