Beispiel #1
0
        /// <summary>
        /// Computes the auto-covariance for all lags.
        /// </summary>
        /// <param name="series">The data series.</param>
        /// <returns>An array of auto-covariance values, with the array index equal to the lag index.</returns>
        /// <remarks>
        /// <para>The computation of the auto-covariance for a given lag is an O(N) operation.
        /// Naively, the computation of the auto-covariance for all N possible lags is therefore an
        /// O(N^2) operation; this is in fact the cost of N invocations of
        /// <see cref="Autocovariance(IReadOnlyList{double},int)"/>.
        /// However, using Fourier techniques, it is possible to simultaneously compute
        /// the auto-covariance for all possible lags in O(N log N) operations. This method
        /// uses the Fourier technique and should be called if you require the auto-covariance
        /// for more than a handful of lag values.</para>
        /// </remarks>
        /// <seealso cref="Autocovariance(IReadOnlyList{double},int)"/>
        /// <see href="https://en.wikipedia.org/wiki/Autocovariance"/>
        public static double[] Autocovariance(this IReadOnlyList <double> series)
        {
            if (series == null)
            {
                throw new ArgumentNullException(nameof(series));
            }

            // To avoid aliasing, we must zero-pad with n zeros.
            Complex[] s = new Complex[2 * series.Count];
            for (int i = 0; i < series.Count; i++)
            {
                s[i] = series[i] - series.Mean();
            }

            FourierTransformer fft = new FourierTransformer(s.Length);

            Complex[] t = fft.Transform(s);

            for (int i = 0; i < t.Length; i++)
            {
                t[i] = MoreMath.Sqr(t[i].Re) + MoreMath.Sqr(t[i].Im);
            }

            Complex[] u = fft.InverseTransform(t);

            double[] c = new double[series.Count];
            for (int i = 0; i < c.Length; i++)
            {
                c[i] = u[i].Re / series.Count;
            }

            return(c);
        }
Beispiel #2
0
        /// <summary>
        /// Computes the autocovariance for all lags.
        /// </summary>
        /// <returns>An array of autocovariance values, with the array index equal to the lag index.</returns>
        /// <remarks>
        /// <para>The computation of the autocovariance for a given lag is an O(N) operation.
        /// Naively, the computation of the autocovariance for all N possible lags is an
        /// O(N^2) operation; this is in fact the cost of N invoations of <see cref="Autocovariance(int)"/>.
        /// However, it is possible using Fourier techniques to simultaneously compute
        /// the autocovariance for all possible lags in O(N log N) operations. This method
        /// uses this Fourier technique and should be called if you require the autocovariance
        /// for more than a handfull of lag values.</para>
        /// </remarks>
        /// <seealso cref="Autocovariance(int)"/>
        public double[] Autocovariance()
        {
            // To avoid aliasing, we must zero-pad with n zeros.
            Complex[] s = new Complex[2 * data.Count];
            for (int i = 0; i < data.Count; i++)
            {
                s[i] = data[i] - data.Mean;
            }

            FourierTransformer fft = new FourierTransformer(s.Length);

            Complex[] t = fft.Transform(s);

            for (int i = 0; i < t.Length; i++)
            {
                t[i] = MoreMath.Sqr(t[i].Re) + MoreMath.Sqr(t[i].Im);
            }

            Complex[] u = fft.InverseTransform(t);

            double[] c = new double[data.Count];
            for (int i = 0; i < c.Length; i++)
            {
                c[i] = u[i].Re / data.Count;
            }

            return(c);
        }
Beispiel #3
0
        public void FourierInverse()
        {
            foreach (int n in sizes)
            {
                Console.WriteLine(n);

                FourierTransformer ft = new FourierTransformer(n);

                Complex[] x = TestUtilities.GenerateComplexValues(0.1, 10.0, n);

                Complex[] y = ft.Transform(x);
                Complex[] z = ft.InverseTransform(y);

                for (int i = 0; i < n; i++)
                {
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(x[i], z[i]));
                }
            }
        }
Beispiel #4
0
        public void TestMethod1()
        {
            int N = 49 * 2;
            FourierTransformer ft = new FourierTransformer(N);

            Complex[] x = new Complex[N];
            x[1] = 1.0;

            Complex[] y = ft.Transform(x);

            Complex[] z = ft.InverseTransform(y);
            //Complex[] z = new Complex[N];

            for (int i = 0; i < x.Length; i++)
            {
                double t = -2.0 * Math.PI / x.Length * i;
                Console.WriteLine("{0} -> {1} {2} -> {3}", x[i], y[i], new Complex(Math.Cos(t), Math.Sin(t)), z[i]);
            }
        }
Beispiel #5
0
        public void FourierSpecialCases()
        {
            for (int n = 2; n <= 10; n++)
            {
                FourierTransformer ft = new FourierTransformer(n);
                Assert.IsTrue(ft.Length == n);

                // transform of uniform is zero frequency only
                Complex[] x1 = new Complex[n];
                for (int i = 0; i < n; i++)
                {
                    x1[i] = 1.0;
                }
                Complex[] y1 = ft.Transform(x1);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(y1[0], n));
                for (int i = 1; i < n; i++)
                {
                    Assert.IsTrue(ComplexMath.Abs(y1[i]) < TestUtilities.TargetPrecision);
                }
                Complex[] z1 = ft.InverseTransform(y1);
                for (int i = 0; i < n; i++)
                {
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(z1[i], 1.0));
                }

                // transform of pulse at 1 are nth roots of unity, read clockwise
                Complex[] x2 = new Complex[n];
                x2[1] = 1.0;
                Complex[] y2 = ft.Transform(x2);
                for (int i = 0; i < n; i++)
                {
                    double t = -2.0 * Math.PI / n * i;
                    Assert.IsTrue(TestUtilities.IsNearlyEqual(y2[i], new Complex(Math.Cos(t), Math.Sin(t))));
                }
            }
        }