コード例 #1
0
        /// <summary>
        /// The internal method for calculating the auto-correlation.
        /// </summary>
        /// <param name="x">The data array to calculate auto-correlation for</param>
        /// <param name="kLow">Min lag to calculate ACF for (0 = no shift with acf=1) must be zero or positive and smaller than x.Length</param>
        /// <param name="kHigh">Max lag (EXCLUSIVE) to calculate ACF for must be positive and smaller than x.Length</param>
        /// <returns>An array with the ACF as a function of the lags k.</returns>
        private static double[] AutoCorrelationFft(double[] x, int kLow, int kHigh)
        {
            if (x == null)
            {
                throw new ArgumentNullException(nameof(x));
            }

            int N = x.Length;    // Sample size

            if (kLow < 0 || kLow >= N)
            {
                throw new ArgumentOutOfRangeException(nameof(kLow), "kMin must be zero or positive and smaller than x.Length");
            }
            if (kHigh < 0 || kHigh >= N)
            {
                throw new ArgumentOutOfRangeException(nameof(kHigh), "kMax must be positive and smaller than x.Length");
            }
            if (N < 1)
            {
                return(new double[0]);
            }

            int nFFT = Euclid.CeilingToPowerOfTwo(N) * 2;

            Complex[] xFFT  = new Complex[nFFT];
            Complex[] xFFT2 = new Complex[nFFT];

            double xDash   = ArrayStatistics.Mean(x);
            double xArrNow = 0.0d;

            // copy values in range and substract mean - all the remaining parts are padded with zero.
            for (int i = 0; i < x.Length; i++)
            {
                xFFT[i] = new Complex(x[i] - xDash, 0.0);    // copy values in range and substract mean
            }

            Fourier.Forward(xFFT, FourierOptions.Matlab);

            // maybe a Vector<Complex> implementation here would be faster
            for (int i = 0; i < xFFT.Length; i++)
            {
                xFFT2[i] = Complex.Multiply(xFFT[i], Complex.Conjugate(xFFT[i]));
            }

            Fourier.Inverse(xFFT2, FourierOptions.Matlab);

            double dc = xFFT2[0].Real;

            double[] result = new double[kHigh - kLow + 1];

            // normalize such that acf[0] would be 1.0
            for (int i = 0; i < (kHigh - kLow + 1); i++)
            {
                result[i] = xFFT2[kLow + i].Real / dc;
            }

            return(result);
        }
コード例 #2
0
 public static Complex Conjugate(this Complex complex)
 {
     return(Complex.Conjugate(complex));
 }
コード例 #3
0
        /// <summary>
        /// Reduces a complex hermitian matrix to a real symmetric tridiagonal matrix using unitary similarity transformations.
        /// </summary>
        /// <param name="matrixA">Source matrix to reduce</param>
        /// <param name="d">Output: Arrays for internal storage of real parts of eigenvalues</param>
        /// <param name="e">Output: Arrays for internal storage of imaginary parts of eigenvalues</param>
        /// <param name="tau">Output: Arrays that contains further information about the transformations.</param>
        /// <param name="order">Order of initial matrix</param>
        /// <remarks>This is derived from the Algol procedures HTRIDI by
        /// Smith, Boyle, Dongarra, Garbow, Ikebe, Klema, Moler, and Wilkinson, Handbook for
        /// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
        /// Fortran subroutine in EISPACK.</remarks>
        internal static void SymmetricTridiagonalize(System.Numerics.Complex[] matrixA, double[] d, double[] e, System.Numerics.Complex[] tau, int order)
        {
            double hh;

            tau[order - 1] = System.Numerics.Complex.One;

            for (var i = 0; i < order; i++)
            {
                d[i] = matrixA[i * order + i].Real;
            }

            // Householder reduction to tridiagonal form.
            for (var i = order - 1; i > 0; i--)
            {
                // Scale to avoid under/overflow.
                var scale = 0.0;
                var h     = 0.0;

                for (var k = 0; k < i; k++)
                {
                    scale = scale + Math.Abs(matrixA[k * order + i].Real) + Math.Abs(matrixA[k * order + i].Imaginary);
                }

                if (scale == 0.0)
                {
                    tau[i - 1] = System.Numerics.Complex.One;
                    e[i]       = 0.0;
                }
                else
                {
                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k * order + i] /= scale;
                        h += matrixA[k * order + i].MagnitudeSquared();
                    }

                    System.Numerics.Complex g = Math.Sqrt(h);
                    e[i] = scale * g.Real;

                    System.Numerics.Complex temp;
                    var im1Oi = (i - 1) * order + i;
                    var f     = matrixA[im1Oi];
                    if (f.Magnitude != 0)
                    {
                        temp            = -(matrixA[im1Oi].Conjugate() * tau[i].Conjugate()) / f.Magnitude;
                        h              += f.Magnitude * g.Real;
                        g               = 1.0 + (g / f.Magnitude);
                        matrixA[im1Oi] *= g;
                    }
                    else
                    {
                        temp           = -tau[i].Conjugate();
                        matrixA[im1Oi] = g;
                    }

                    if ((f.Magnitude == 0) || (i != 1))
                    {
                        f = System.Numerics.Complex.Zero;
                        for (var j = 0; j < i; j++)
                        {
                            var tmp = System.Numerics.Complex.Zero;
                            var jO  = j * order;
                            // Form element of A*U.
                            for (var k = 0; k <= j; k++)
                            {
                                tmp += matrixA[k * order + j] * matrixA[k * order + i].Conjugate();
                            }

                            for (var k = j + 1; k <= i - 1; k++)
                            {
                                tmp += matrixA[jO + k].Conjugate() * matrixA[k * order + i].Conjugate();
                            }

                            // Form element of P
                            tau[j] = tmp / h;
                            f     += (tmp / h) * matrixA[jO + i];
                        }

                        hh = f.Real / (h + h);

                        // Form the reduced A.
                        for (var j = 0; j < i; j++)
                        {
                            f      = matrixA[j * order + i].Conjugate();
                            g      = tau[j] - (hh * f);
                            tau[j] = g.Conjugate();

                            for (var k = 0; k <= j; k++)
                            {
                                matrixA[k * order + j] -= (f * tau[k]) + (g * matrixA[k * order + i]);
                            }
                        }
                    }

                    for (var k = 0; k < i; k++)
                    {
                        matrixA[k * order + i] *= scale;
                    }

                    tau[i - 1] = temp.Conjugate();
                }

                hh   = d[i];
                d[i] = matrixA[i * order + i].Real;
                matrixA[i * order + i] = new System.Numerics.Complex(hh, scale * Math.Sqrt(h));
            }

            hh         = d[0];
            d[0]       = matrixA[0].Real;
            matrixA[0] = hh;
            e[0]       = 0.0;
        }