Пример #1
0
        /// <summary>
        /// Computes an Fast Fourier Transform.
        /// </summary>
        /// <param name="data">Array of complex numbers. This array provides the input data and is used to store the result of the FFT.</param>
        /// <param name="exponent">The exponent n.</param>
        /// <param name="mode">The <see cref="FftMode"/> to use. Use <see cref="FftMode.Forward"/> as the default value.</param>
        public static void Fft(Complex[] data, int exponent, FftMode mode = FftMode.Forward)
        {
            //count; if exponent = 12 -> c = 2^12 = 4096
            int c = (int)Math.Pow(2, exponent);

            //binary inversion
            Inverse(data, c);

            int j0, j1, j2 = 1;
            float n0, n1, tr, ti, m;
            float v0 = -1, v1 = 0;

            //move to outer scope to optimize performance
            int j, i;

            for (int l = 0; l < exponent; l++)
            {
                n0 = 1;
                n1 = 0;
                j1 = j2;
                j2 <<= 1; //j2 * 2

                for (j = 0; j < j1; j++)
                {
                    for (i = j; i < c; i += j2)
                    {
                        j0 = i + j1;
                        //--
                        tr = n0 * data[j0].Real - n1 * data[j0].Imaginary;
                        ti = n0 * data[j0].Imaginary + n1 * data[j0].Real;
                        //--
                        data[j0].Real = data[i].Real - tr;
                        data[j0].Imaginary = data[i].Imaginary - ti;
                        //add
                        data[i].Real += tr;
                        data[i].Imaginary += ti;
                    }

                    //calc coeff
                    m = v0 * n0 - v1 * n1;
                    n1 = v1 * n0 + v0 * n1;
                    n0 = m;
                }

                if (mode == FftMode.Forward)
                {
                    v1 = (float)Math.Sqrt((1f - v0) / 2f);
                }
                else
                {
                    v1 = (float)-Math.Sqrt((1f - v0) / 2f);
                }
                v0 = (float)Math.Sqrt((1f + v0) / 2f);
            }

            if (mode == FftMode.Forward)
            {
                Forward(data, c);
            }
        }
        /// <summary>
        /// Computes an Fast Fourier Transform.
        /// </summary>
        /// <param name="data">Array of complex numbers. This array provides the input data and is used to store the result of the FFT.</param>
        /// <param name="exponent">The exponent n.</param>
        /// <param name="mode">The <see cref="FftMode"/> to use. Use <see cref="FftMode.Forward"/> as the default value.</param>
        public static void Fft(Complex[] data, int exponent, FftMode mode = FftMode.Forward)
        {
            //count; if exponent = 12 -> c = 2^12 = 4096
            int c = (int)Math.Pow(2, exponent);

            //binary inversion
            Inverse(data, c);

            int   j0, j1, j2 = 1;
            float n0, n1, tr, ti, m;
            float v0 = -1, v1 = 0;

            //move to outer scope to optimize performance
            int j, i;

            for (int l = 0; l < exponent; l++)
            {
                n0   = 1;
                n1   = 0;
                j1   = j2;
                j2 <<= 1; //j2 * 2

                for (j = 0; j < j1; j++)
                {
                    for (i = j; i < c; i += j2)
                    {
                        j0 = i + j1;
                        //--
                        tr = n0 * data[j0].Real - n1 * data[j0].Imaginary;
                        ti = n0 * data[j0].Imaginary + n1 * data[j0].Real;
                        //--
                        data[j0].Real      = data[i].Real - tr;
                        data[j0].Imaginary = data[i].Imaginary - ti;
                        //add
                        data[i].Real      += tr;
                        data[i].Imaginary += ti;
                    }

                    //calc coeff
                    m  = v0 * n0 - v1 * n1;
                    n1 = v1 * n0 + v0 * n1;
                    n0 = m;
                }

                if (mode == FftMode.Forward)
                {
                    v1 = (float)Math.Sqrt((1f - v0) / 2f);
                }
                else
                {
                    v1 = (float)-Math.Sqrt((1f - v0) / 2f);
                }
                v0 = (float)Math.Sqrt((1f + v0) / 2f);
            }

            if (mode == FftMode.Forward)
            {
                Forward(data, c);
            }
        }
Пример #3
0
        /// <summary>
        /// Performs forward transform to the specified span.
        /// </summary>
        /// <param name="span">The span.</param>
        /// <param name="mode">The FFT's Mode.</param>
        private static void Perform(Span <ComplexF> span, FftMode mode)
        {
            double thetaBase = mode == FftMode.Forward ? -Tau : Tau;

            if (span.Length < 2)
            {
                return;
            }
            Perform2(span);
            if (span.Length < 4)
            {
                return;
            }
            switch (mode)
            {
            case FftMode.Forward:
                Perform4Forward(span);
                break;

            case FftMode.Backward:
                Perform4Backward(span);
                break;
            }
            var index = 3;

            for (int m = 8; m <= span.Length; m <<= 1)
            {
                ComplexF t, u;
                Complex  omega  = 1;
                int      mHalf  = m >> 1;
                var      omegaM = GetValueToMultiply(index++);
                omegaM = mode == FftMode.Forward ? Complex.Conjugate(omegaM) : omegaM;
                Span <ComplexF> omegas = stackalloc ComplexF[mHalf];
                for (int i = 0; i < omegas.Length; i++)
                {
                    omegas[i] = (ComplexF)omega;
                    omega    *= omegaM;
                }
                for (int k = 0; k < span.Length; k += m)
                {
                    //Preset addressing reduces addition and boundary checks.
                    var spanA = span.Slice(k, omegas.Length);
                    var spanB = span.Slice(k + mHalf, spanA.Length);
                    for (int j = 0; j < omegas.Length; j++)
                    {
                        t        = omegas[j] * spanB[j];
                        u        = spanA[j];
                        spanA[j] = u + t;
                        spanB[j] = u - t;
                    }
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Performs forward transform to the specified span.
        /// </summary>
        /// <param name="span">The span.</param>
        /// <param name="mode">The FFT's Mode.</param>
        private static void Perform(Span <Complex> span, FftMode mode)
        {
            double  thetaBase = 2 * Math.PI * (mode == FftMode.Forward ? -1 : 1);
            Complex omega, omegaM;

            if (span.Length >= 2)
            {
                Perform2(span);
                if (span.Length >= 4)
                {
                    switch (mode)
                    {
                    case FftMode.Forward:
                        Perform4Forward(span);
                        break;

                    case FftMode.Backward:
                        Perform4Backward(span);
                        break;
                    }
                    for (int m = 8; m <= span.Length; m <<= 1)
                    {
                        Complex t, u;
                        double  theta = thetaBase / m;
                        omegaM = Complex.FromPolarCoordinates(1, theta);
                        for (int k = 0; k < span.Length; k += m)
                        {
                            omega = 1;
                            int mHalf = m >> 1;
                            //Preset addressing reduces addition and boundary checks.
                            var spanA = span.Slice(k, mHalf);
                            var spanB = span.Slice(k + mHalf, spanA.Length);
                            for (int j = 0; j < spanA.Length; j++)
                            {
                                t        = omega * spanB[j];
                                u        = spanA[j];
                                spanA[j] = u + t;
                                spanB[j] = u - t;
                                omega   *= omegaM;
                            }
                        }
                    }
                }
            }
        }
Пример #5
0
 public static void FFT1(Complex[] data, int exponent, FftMode mode)
 {
     Fft(data, exponent, mode);
 }
 public static void FFT1(Complex[] data, int exponent, FftMode mode)
 {
     Fft(data, exponent, mode);
 }