/// <summary>
 /// Inplace Forward Transformation in one dimension. Size must be Power of Two.
 /// </summary>
 /// <param name="samplePairs">Complex samples (even = real, odd = imaginary). Length must be a power of two.</param>
 public void TransformForward(double[] samplePairs)
 {
     if (Fn.CeilingToPowerOf2(samplePairs.Length) != samplePairs.Length)
     {
         throw new ArgumentException(Resources.ArgumentPowerOfTwo, "samplePairs");
     }
     _fft.DiscreteFourierTransform(samplePairs, true, _convention);
 }
        /// <summary>
        /// Outplace Forward Transformation in one dimension for two vectors with the same length.
        /// Size must be Power of Two.
        /// </summary>
        /// <param name="samples1">Real samples. Length must be a power of two.</param>
        /// <param name="samples2">Real samples. Length must be a power of two.</param>
        public void TransformForward(double[] samples1, double[] samples2,
                                     out double[] fftReal1, out double[] fftImag1, out double[] fftReal2, out double[] fftImag2)
        {
            if (samples1.Length != samples2.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLengths, "samples2");
            }
            if (Fn.CeilingToPowerOf2(samples1.Length) != samples1.Length)
            {
                throw new ArgumentException(Resources.ArgumentPowerOfTwo, "samples1");
            }

            int numSamples = samples1.Length;
            int length     = numSamples << 1;

            // Pack together to one complex vector

            double[] complex = new double[length];
            for (int i = 0, j = 0; i < numSamples; i++, j += 2)
            {
                complex[j]     = samples1[i];
                complex[j + 1] = samples2[i];
            }

            // Transform complex vector

            _fft.DiscreteFourierTransform(complex, true, _convention);

            // Reconstruct data for the two vectors by using symmetries

            fftReal1 = new double[numSamples];
            fftImag1 = new double[numSamples];
            fftReal2 = new double[numSamples];
            fftImag2 = new double[numSamples];

            double h1r, h2i, h2r, h1i;

            fftReal1[0] = complex[0];
            fftReal2[0] = complex[1];
            fftImag1[0] = fftImag2[0] = 0d;
            for (int i = 1, j = 2; j <= numSamples; i++, j += 2)
            {
                h1r = 0.5 * (complex[j] + complex[length - j]);
                h1i = 0.5 * (complex[j + 1] - complex[length + 1 - j]);
                h2r = 0.5 * (complex[j + 1] + complex[length + 1 - j]);
                h2i = -0.5 * (complex[j] - complex[length - j]);

                fftReal1[i] = h1r;
                fftImag1[i] = h1i;
                fftReal1[numSamples - i] = h1r;
                fftImag1[numSamples - i] = -h1i;

                fftReal2[i] = h2r;
                fftImag2[i] = h2i;
                fftReal2[numSamples - i] = h2r;
                fftImag2[numSamples - i] = -h2i;
            }
        }
        TransformForward(
            double[] samples1,
            double[] samples2,
            out double[] fftReal1,
            out double[] fftImag1,
            out double[] fftReal2,
            out double[] fftImag2)
        {
            if (samples1.Length != samples2.Length)
            {
                throw new ArgumentException(Properties.LocalStrings.ArgumentVectorsSameLengths, "samples2");
            }

            if (Fn.CeilingToPowerOf2(samples1.Length) != samples1.Length)
            {
                throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwo, "samples1");
            }

            int numSamples = samples1.Length;
            int length     = numSamples << 1;

            /* Pack together to one complex vector */

            double[] complex = new double[length];
            for (int i = 0, j = 0; i < numSamples; i++, j += 2)
            {
                complex[j]     = samples1[i];
                complex[j + 1] = samples2[i];
            }

            /* Transform complex vector */

            _fft.DiscreteFourierTransform(complex, true, _convention);

            /* Reconstruct data for the two vectors by using symmetries */

            fftReal1 = new double[numSamples];
            fftImag1 = new double[numSamples];
            fftReal2 = new double[numSamples];
            fftImag2 = new double[numSamples];

            fftReal1[0] = complex[0];
            fftReal2[0] = complex[1];
            fftImag1[0] = fftImag2[0] = 0d;
            for (int i = 1, j = 2; j <= numSamples; i++, j += 2)
            {
                double h1Real = 0.5 * (complex[j] + complex[length - j]);
                double h1Imag = 0.5 * (complex[j + 1] - complex[length + 1 - j]);
                double h2Real = 0.5 * (complex[j + 1] + complex[length + 1 - j]);
                double h2Imag = -0.5 * (complex[j] - complex[length - j]);

                fftReal1[i] = h1Real;
                fftImag1[i] = h1Imag;
                fftReal1[numSamples - i] = h1Real;
                fftImag1[numSamples - i] = -h1Imag;

                fftReal2[i] = h2Real;
                fftImag2[i] = h2Imag;
                fftReal2[numSamples - i] = h2Real;
                fftImag2[numSamples - i] = -h2Imag;
            }
        }