public virtual STuple <Vector, Vector> Apply2(STuple <Vector, Vector> input)
        {
            Vector inputReal2 = input.Value1;
            Vector inputImag2 = input.Value2;

            if (inputImag2 == null)
            {
                inputImag2 = new Vector(inputReal2.Length);
            }

            Vector outputReal2      = new Vector(inputReal2.Length);
            Vector outputImaginary2 = new Vector(inputImag2.Length);

            IArrayReadable <float>  inputReal       = inputReal2;
            IArrayReadable <float>  inputImag       = inputImag2;
            IArrayWriteable <float> outputReal      = outputReal2;
            IArrayWriteable <float> outputImaginary = outputImaginary2;

            dft(inputReal, inputImag, outputReal, outputImaginary);

            return(new STuple <Vector, Vector>(outputReal2, outputImaginary2));
        }
        public void dft(IArrayReadable <float> inputReal, IArrayReadable <float> inputImag, IArrayWriteable <float> outputReal, IArrayWriteable <float> outputImaginary)
        {
            //Xk = sigma(n=0,N-1,xn*e^(-2pi*i*n*k/N)
            //e^(i*theta) = cos(theta) + i*sin(theta)

            int length = inputReal.Length;

            int   k;
            int   n;
            float real;
            float imag;
            float theta;

            float twoPiDivLength = (float)(2 * Math.PI / length);
            float scale;
            float valueReal;
            float valueImag;
            float ca;
            float sa;

            SetupLookupTables(length);
            float[,] cc = null;
            float[,] ss = null;
            if (CosineLookupTables.ContainsKey(length))
            {
                cc = CosineLookupTables[length];
                ss = SineLookupTables[length];
            }

            for (k = 0; k < length; k++)
            {
                real = 0;
                imag = 0;

                if (cc == null)
                {
                    scale = k * twoPiDivLength * (IsInverse ? -1 : 1);
                    for (n = 0; n < length; n++)
                    {
                        theta = n * scale;
                        ca    = (float)Math.Cos(theta);
                        sa    = (float)Math.Sin(theta);

                        valueReal = inputReal[n];
                        valueImag = inputImag[n];
                        real     += valueReal * ca - valueImag * sa;
                        imag     += valueReal * sa + valueImag * ca;
                    }
                }
                else if (IsInverse)
                {
                    for (n = 0; n < length; n++)
                    {
                        ca = cc[k, n];
                        sa = -ss[k, n];

                        valueReal = inputReal[n];
                        valueImag = inputImag[n];
                        real     += valueReal * ca - valueImag * sa;
                        imag     += valueReal * sa + valueImag * ca;
                    }
                }
                else
                {
                    for (n = 0; n < length; n++)
                    {
                        ca = cc[k, n];
                        sa = ss[k, n];

                        valueReal = inputReal[n];
                        valueImag = inputImag[n];
                        real     += valueReal * ca - valueImag * sa;
                        imag     += valueReal * sa + valueImag * ca;
                    }
                }

                outputReal[k]      = ScaleForInverse(real, length);
                outputImaginary[k] = ScaleForInverse(imag, length);
            }
        }