TransformBackward(
            Complex[] samples,
            params int[] dimensionLengths
            )
        {
            for (int i = 0; i < dimensionLengths.Length; i++)
            {
                if (Fn.CeilingToPowerOf2(dimensionLengths[i]) != dimensionLengths[i])
                {
                    throw new ArgumentException(Resources.ArgumentPowerOfTwoEveryDimension, "dimensionLengths");
                }
            }

            double[] samplePairs = new double[samples.Length << 1];
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samplePairs[j]     = samples[i].Real;
                samplePairs[j + 1] = samples[i].Imag;
            }
            _fft.DiscreteFourierTransformMultiDim(samplePairs, dimensionLengths, false, _convention);
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samples[i].Real = samplePairs[j];
                samples[i].Imag = samplePairs[j + 1];
            }
        }
        TransformForward(
            double[] samples,
            out double[] fftReal,
            out double[] fftImag,
            params int[] dimensionLengths)
        {
            for (int i = 0; i < dimensionLengths.Length; i++)
            {
                if (Fn.CeilingToPowerOf2(dimensionLengths[i]) != dimensionLengths[i])
                {
                    throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwoEveryDimension, "dimensionLengths");
                }
            }

            /* TODO: Implement real version (at the moment this is just a wrapper to the complex version)! */

            double[] samplePairs = new double[samples.Length << 1];
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samplePairs[j] = samples[i];
            }

            _fft.DiscreteFourierTransformMultiDim(samplePairs, dimensionLengths, true, _convention);

            fftReal = new double[samples.Length];
            fftImag = new double[samples.Length];
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                fftReal[i] = samplePairs[j];
                fftImag[i] = samplePairs[j + 1];
            }
        }
        /// <summary>
        /// Outplace Backward Transformation in multiple dimensions.
        /// Size must be Power of Two in each dimension.
        /// The Data is expected to be ordered such that the last index changes most rapidly (in 2D this means row-by-row when indexing as [y,x]).
        /// </summary>
        public void TransformBackward(double[] fftReal, double[] fftImag, out double[] samples, params int[] dimensionLengths)
        {
            if (fftReal.Length != fftImag.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLengths);
            }
            for (int i = 0; i < dimensionLengths.Length; i++)
            {
                if (Fn.CeilingToPowerOf2(dimensionLengths[i]) != dimensionLengths[i])
                {
                    throw new ArgumentException(Resources.ArgumentPowerOfTwoEveryDimension, "dimensionLengths");
                }
            }

            // TODO: Implement real version (at the moment this is just a wrapper to the complex version)!

            double[] samplePairs = new double[fftReal.Length << 1];
            for (int i = 0, j = 0; i < fftReal.Length; i++, j += 2)
            {
                samplePairs[j]     = fftReal[i];
                samplePairs[j + 1] = fftImag[i];
            }

            _fft.DiscreteFourierTransformMultiDim(samplePairs, dimensionLengths, false, _convention);

            samples = new double[fftReal.Length];
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samples[i] = samplePairs[j];
            }
        }
 /// <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;
            }
        }
Beispiel #6
0
        TransformBackward(double[] samplePairs)
        {
            if (Fn.CeilingToPowerOf2(samplePairs.Length) != samplePairs.Length)
            {
                throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwo, "samplePairs");
            }

            _fft.DiscreteFourierTransform(samplePairs, false, _convention);
        }
        TransformBackward(
            double[] fftReal,
            double[] fftImag,
            out double[] samples
            )
        {
            if (fftReal.Length != fftImag.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLengths);
            }

            if (Fn.CeilingToPowerOf2(fftReal.Length) != fftReal.Length)
            {
                throw new ArgumentException(Resources.ArgumentPowerOfTwo, "samples");
            }

            int    length            = fftReal.Length;
            int    numSamples        = length >> 1;
            double expSignConvention = (_convention & TransformationConvention.InverseExponent) > 0 ? -1d : 1d;

            double theta = -Constants.Pi / numSamples;
            double wtemp = Trig.Sine(0.5 * theta);
            double wpr   = -2.0 * wtemp * wtemp;
            double wpi   = expSignConvention * Trig.Sine(theta);
            double wr    = 1.0 + wpr;
            double wi    = wpi;

            samples = new double[length];

            double h1r, h2i, h2r, h1i;

            // TODO: may be 1 <--> 0 swapped?
            samples[1] = 0.5 * (fftReal[0] - fftReal[numSamples]);
            samples[0] = 0.5 * (fftReal[0] + fftReal[numSamples]);

            for (int i = 1, j = 2; j <= numSamples; i++, j += 2)
            {
                h1r = 0.5 * (fftReal[i] + fftReal[numSamples - i]);
                h1i = 0.5 * (fftImag[i] - fftImag[numSamples - i]);
                h2r = -0.5 * (fftImag[i] + fftImag[numSamples - i]);
                h2i = 0.5 * (fftReal[i] - fftReal[numSamples - i]);

                samples[j]              = h1r + wr * h2r + wi * h2i;
                samples[j + 1]          = h1i + wr * h2i - wi * h2r;
                samples[length - j]     = h1r - wr * h2r - wi * h2i;
                samples[length + 1 - j] = -h1i + wr * h2i - wi * h2r;

                wr = (wtemp = wr) * wpr - wi * wpi + wr;
                wi = wi * wpr + wtemp * wpi + wi;
            }

            // Transform odd and even vectors (packed as one complex vector)

            _fft.DiscreteFourierTransform(samples, false, _convention);
        }
 /// <summary>
 /// Inplace Backward Transformation in multiple dimensions.
 /// Size must be Power of Two in each dimension.
 /// The Data is expected to be ordered such that the last index changes most rapidly (in 2D this means row-by-row when indexing as [y,x]).
 /// </summary>
 /// <param name="samplePairs">Complex samples (even = real, odd = imaginary). Length must be a power of two in each dimension.</param>
 public void TransformBackward(double[] samplePairs, params int[] dimensionLengths)
 {
     for (int i = 0; i < dimensionLengths.Length; i++)
     {
         if (Fn.CeilingToPowerOf2(dimensionLengths[i]) != dimensionLengths[i])
         {
             throw new ArgumentException(Resources.ArgumentPowerOfTwoEveryDimension, "dimensionLengths");
         }
     }
     _fft.DiscreteFourierTransformMultiDim(samplePairs, dimensionLengths, false, _convention);
 }
Beispiel #9
0
        public double[] ExtendToPowerOf2Length(double[] samples)
        {
            int newlen = Fn.CeilingToPowerOf2(samples.Length);

            double[] ret = new double[newlen];
            for (int i = 0; i < samples.Length; i++)
            {
                ret[i] = samples[i];
            }
            // rest is padded with zero.
            return(ret);
        }
Beispiel #10
0
        TransformForward(
            double[] samplePairs,
            params int[] dimensionLengths)
        {
            for (int i = 0; i < dimensionLengths.Length; i++)
            {
                if (Fn.CeilingToPowerOf2(dimensionLengths[i]) != dimensionLengths[i])
                {
                    throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwoEveryDimension, "dimensionLengths");
                }
            }

            _fft.DiscreteFourierTransformMultiDim(samplePairs, dimensionLengths, true, _convention);
        }
        TransformBackward(
            double[] fftReal1,
            double[] fftImag1,
            double[] fftReal2,
            double[] fftImag2,
            out double[] samples1,
            out double[] samples2
            )
        {
            if (fftReal1.Length != fftImag1.Length || fftReal2.Length != fftImag2.Length || fftReal1.Length != fftReal2.Length)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLengths);
            }

            if (Fn.CeilingToPowerOf2(fftReal1.Length) != fftReal1.Length)
            {
                throw new ArgumentException(Resources.ArgumentPowerOfTwo, "fftReal1");
            }

            int numSamples = fftReal1.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]     = fftReal1[i] - fftImag2[i];
                complex[j + 1] = fftImag1[i] + fftReal2[i];
            }

            // Transform complex vector

            _fft.DiscreteFourierTransform(complex, false, _convention);

            // Reconstruct data for the two vectors

            samples1 = new double[numSamples];
            samples2 = new double[numSamples];

            for (int i = 0, j = 0; i < numSamples; i++, j += 2)
            {
                samples1[i] = complex[j];
                samples2[i] = complex[j + 1];
            }
        }
        public void TestSpecialFunctions_CeilingToPowerOf2()
        {
            Assert.That(Fn.CeilingToPowerOf2(0), Is.EqualTo(0), "A");
            Assert.That(Fn.CeilingToPowerOf2(1), Is.EqualTo(1), "B");
            Assert.That(Fn.CeilingToPowerOf2(2), Is.EqualTo(2), "C");
            Assert.That(Fn.CeilingToPowerOf2(3), Is.EqualTo(4), "D");
            Assert.That(Fn.CeilingToPowerOf2(4), Is.EqualTo(4), "E");

            for (int i = 2; i < 31; i++)
            {
                int pow = (int)Math.Pow(2.0, i);
                Assert.That(Fn.CeilingToPowerOf2(pow), Is.EqualTo(pow), pow.ToString());
                Assert.That(Fn.CeilingToPowerOf2(pow - 1), Is.EqualTo(pow), pow.ToString() + "-1");
            }

            Assert.That(Fn.CeilingToPowerOf2((int.MaxValue >> 1) + 1), Is.EqualTo((int.MaxValue >> 1) + 1), "Y");
            Assert.That(Fn.CeilingToPowerOf2((int.MaxValue >> 1)), Is.EqualTo((int.MaxValue >> 1) + 1), "Z");
        }
 /// <summary>
 /// Inplace Backward Transformation in one dimension. Size must be Power of Two.
 /// </summary>
 /// <param name="samples">Complex samples. Length must be a power of two.</param>
 /// <remarks>
 /// This method provides a simple shortcut if your data is already available as
 /// <see cref="Complex"/> type instances. However, if not, consider using the
 /// overloaded method with double pairs instead, it requires less internal copying.
 /// </remarks>
 public void TransformBackward(Complex[] samples)
 {
     if (Fn.CeilingToPowerOf2(samples.Length) != samples.Length)
     {
         throw new ArgumentException(Resources.ArgumentPowerOfTwo, "samplePairs");
     }
     double[] samplePairs = new double[samples.Length << 1];
     for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
     {
         samplePairs[j]     = samples[i].Real;
         samplePairs[j + 1] = samples[i].Imag;
     }
     _fft.DiscreteFourierTransform(samplePairs, false, _convention);
     for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
     {
         samples[i].Real = samplePairs[j];
         samples[i].Imag = samplePairs[j + 1];
     }
 }
Beispiel #14
0
        TransformForward(Complex[] samples)
        {
            if (Fn.CeilingToPowerOf2(samples.Length) != samples.Length)
            {
                throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwo, "samples");
            }

            double[] samplePairs = new double[samples.Length << 1];
            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samplePairs[j]     = samples[i].Real;
                samplePairs[j + 1] = samples[i].Imag;
            }

            _fft.DiscreteFourierTransform(samplePairs, true, _convention);

            for (int i = 0, j = 0; i < samples.Length; i++, j += 2)
            {
                samples[i].Real = samplePairs[j];
                samples[i].Imag = samplePairs[j + 1];
            }
        }
        TransformForward(
            double[] samples,
            out double[] fftReal,
            out double[] fftImag)
        {
            if (Fn.CeilingToPowerOf2(samples.Length) != samples.Length)
            {
                throw new ArgumentException(Properties.LocalStrings.ArgumentPowerOfTwo, "samples");
            }

            int    length            = samples.Length;
            int    numSamples        = length >> 1;
            double expSignConvention = (_convention & TransformationConvention.InverseExponent) > 0 ? -1d : 1d;

            // Transform odd and even vectors (packed as one complex vector)

            // We work on a copy so the original array is not changed.
            double[] complex = new double[length];
            for (int i = 0; i < complex.Length; i++)
            {
                complex[i] = samples[i];
            }

            _fft.DiscreteFourierTransform(complex, true, _convention);

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

            double theta = Constants.Pi / numSamples;
            double wtemp = Trig.Sine(0.5 * theta);
            double wpr   = -2.0 * wtemp * wtemp;
            double wpi   = expSignConvention * Trig.Sine(theta);
            double wr    = 1.0 + wpr;
            double wi    = wpi;

            fftReal = new double[length];
            fftImag = new double[length];

            fftImag[0]          = fftImag[numSamples] = 0d;
            fftReal[0]          = complex[0] + complex[1];
            fftReal[numSamples] = complex[0] - complex[1];
            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]);

                fftReal[i] = h1Real + (wr * h2Real) + (wi * h2Imag);
                fftImag[i] = h1Imag + (wr * h2Imag) - (wi * h2Real);
                fftReal[numSamples - i] = h1Real - (wr * h2Real) - (wi * h2Imag);
                fftImag[numSamples - i] = -h1Imag + (wr * h2Imag) - (wi * h2Real);

                // For consistency and completeness we also provide the
                // negative spectrum, even though it's redundant in the real case.
                fftReal[numSamples + i] = fftReal[numSamples - i];
                fftImag[numSamples + i] = -fftImag[numSamples - i];
                fftReal[length - i]     = fftReal[i];
                fftImag[length - i]     = -fftImag[i];

                wr = ((wtemp = wr) * wpr) - (wi * wpi) + wr;
                wi = (wi * wpr) + (wtemp * wpi) + wi;
            }
        }
        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;
            }
        }