Esempio n. 1
0
        /// <summary>
        /// Performs a complex-to-real inverse fast fourier transformation.
        /// </summary>
        /// <seealso cref="http://www.fftw.org/fftw3_doc/One_002dDimensional-DFTs-of-Real-Data.html#One_002dDimensional-DFTs-of-Real-Data"/>
        /// <seealso cref="http://www.fftw.org/fftw3_doc/Multi_002dDimensional-DFTs-of-Real-Data.html#Multi_002dDimensional-DFTs-of-Real-Data"/>
        public static void IFFT(IPinnedArray <Complex> input, IPinnedArray <double> output, PlannerFlags plannerFlags = PlannerFlags.Default, int nThreads = 1)
        {
            if ((plannerFlags & PlannerFlags.Estimate) == PlannerFlags.Estimate)
            {
                using (var plan = FftwPlanRC.Create(output, input, DftDirection.Backwards, plannerFlags, nThreads))
                {
                    plan.Execute();
                    return;
                }
            }

            using (var plan = FftwPlanRC.Create(output, input, DftDirection.Backwards, plannerFlags | PlannerFlags.WisdomOnly, nThreads))
            {
                if (plan != null)
                {
                    plan.Execute();
                    return;
                }
            }

            /// If with <see cref="PlannerFlags.WisdomOnly"/> no plan can be created
            /// and <see cref="PlannerFlags.Estimate"/> is not specified, we use
            /// a different buffer to avoid overwriting the input
            using (var bufferContainer = _bufferPool.RequestBuffer(input.Length * Marshal.SizeOf <Complex>() + MemoryAlignment))
                using (var buffer = new AlignedArrayComplex(bufferContainer.Buffer, MemoryAlignment, input.GetSize()))
                    using (var plan = FftwPlanRC.Create(output, buffer, DftDirection.Backwards, plannerFlags, nThreads))
                    {
                        input.CopyTo(plan.BufferComplex);
                        plan.Execute();
                    }
        }
Esempio n. 2
0
        static void doBandPass(IPinnedArray <Complex> trans, int[] passIndexRange)
        {
            var j1          = passIndexRange[0];
            var j2          = passIndexRange[1];
            var lenPositive = trans.Length / 2 + trans.Length % 2;

            //positive freq
            for (int i = 0; i < j1; i++)
            {
                trans[i] = 0;
            }
            for (int i = j2 + 1; i < lenPositive; i++)
            {
                trans[i] = 0;
            }

            //negative freq
            j1 = trans.Length - j1;
            j2 = trans.Length - j2;
            for (int i = lenPositive; i < j2; i++)
            {
                trans[i] = 0;
            }
            for (int i = j1 + 1; i < trans.Length; i++)
            {
                trans[i] = 0;
            }
        }
Esempio n. 3
0
        public static void CopyTo <T>(this IPinnedArray <T> src, IPinnedArray <T> dst, int srcIndex, int dstIndex, int count)
            where T : struct
        {
            if (count < 0 || count > src.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            if (count > dst.Length)
            {
                throw new ArgumentException(nameof(dst), "Destination is not large enough.");
            }
            if (srcIndex + count > src.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(srcIndex));
            }
            if (dstIndex + count > src.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(dstIndex));
            }

            int sizeOfT = Marshal.SizeOf <T>();

            unsafe
            {
                void *pSrc = new IntPtr(src.Pointer.ToInt64() + srcIndex * sizeOfT).ToPointer();
                void *pDst = new IntPtr(dst.Pointer.ToInt64() + dstIndex * sizeOfT).ToPointer();
                System.Buffer.MemoryCopy(pSrc, pDst, (long)dst.Length * sizeOfT, (long)count * sizeOfT);
            }
        }
Esempio n. 4
0
        protected override void VerifyMinSize(IPinnedArray <double> bufferReal, IPinnedArray <Complex> bufferComplex, int[] n)
        {
            int sizeComplex;
            int sizeReal = 1;

            checked
            {
                for (int i = 0; i < n.Length - 1; i++)
                {
                    sizeReal *= n[i];
                }
                sizeComplex = sizeReal * (n[n.Length - 1] / 2 + 1);
                sizeReal   *= n[n.Length - 1];
            }

            if (bufferReal.Length < sizeReal)
            {
                throw new ArgumentException($"{nameof(bufferReal)} is too small.");
            }

            if (bufferComplex.Length < sizeComplex)
            {
                throw new ArgumentException($"{nameof(bufferComplex)} is too small.");
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new plan using the provided input and output buffers.
        /// These buffers may be overwritten during initialization.
        /// </summary>
        public static FftwPlanRC Create(IPinnedArray <double> bufferReal, IPinnedArray <Complex> bufferComplex, DftDirection direction, PlannerFlags plannerFlags = PlannerFlags.Default, int nThreads = 1)
        {
            FftwPlanRC plan = new FftwPlanRC(bufferReal, bufferComplex, bufferReal.Rank, bufferReal.GetSize(), true, direction, plannerFlags, nThreads);

            if (plan.IsZero)
            {
                return(null);
            }
            return(plan);
        }
Esempio n. 6
0
 FftwPlanR2R(IPinnedArray <Double> input, IPinnedArray <Double> output, int rank, int[] n, bool verifyRankAndSize, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
     : base(input, output, rank, n, verifyRankAndSize, direction, plannerFlags, 1)
 {
     //int[] ns = input.GetSize();
     //lock (FftwInterop.Lock)
     //{
     //    //_plan = FftwInterop.fftw_plan_r2r(rank,ns,input.Pointer,output.Pointer,direction,plannerFlags);
     //    _plan = GetPlan(rank, n, input.Pointer, output.Pointer, direction, plannerFlags);
     //}
 }
Esempio n. 7
0
        internal static FftwPlanRC Create(IPinnedArray <double> bufferReal, IPinnedArray <Complex> bufferComplex, int rank, int[] n, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
        {
            FftwPlanRC plan = new FftwPlanRC(bufferReal, bufferComplex, rank, n, false, direction, plannerFlags, nThreads);

            if (plan.IsZero)
            {
                return(null);
            }
            return(plan);
        }
Esempio n. 8
0
        internal static FftwPlanC2C Create(IPinnedArray <Complex> input, IPinnedArray <Complex> output, int rank, int[] n, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
        {
            FftwPlanC2C plan = new FftwPlanC2C(input, output, rank, n, false, direction, plannerFlags, nThreads);

            if (plan.IsZero)
            {
                return(null);
            }
            return(plan);
        }
Esempio n. 9
0
        /// <summary>
        /// Initializes a new plan using the provided input and output buffers.
        /// These buffers may be overwritten during initialization.
        /// </summary>
        public static FftwPlanC2C Create(IPinnedArray <Complex> input, IPinnedArray <Complex> output, DftDirection direction, PlannerFlags plannerFlags = PlannerFlags.Default, int nThreads = 1)
        {
            FftwPlanC2C plan = new FftwPlanC2C(input, output, input.Rank, input.GetSize(), true, direction, plannerFlags, nThreads);

            if (plan.IsZero)
            {
                return(null);
            }
            return(plan);
        }
Esempio n. 10
0
        protected override void VerifyMinSize(IPinnedArray <Complex> input, IPinnedArray <Complex> output, int[] n)
        {
            int size = Utils.GetTotalSize(n);

            if (input.Length < size)
            {
                throw new ArgumentException($"{nameof(input)} is too small.");
            }

            if (output.Length < size)
            {
                throw new ArgumentException($"{nameof(output)} is too small.");
            }
        }
Esempio n. 11
0
 protected override void VerifyRankAndSize(IPinnedArray <Complex> input, IPinnedArray <Complex> output)
 {
     if (input.Rank != output.Rank)
     {
         throw new ArgumentException($"{nameof(input)} and {nameof(output)} must have the same rank and size.");
     }
     for (int i = 0; i < input.Rank; i++)
     {
         if (input.GetLength(i) != output.GetLength(i))
         {
             throw new ArgumentException($"{nameof(input)} and {nameof(output)} must have the same rank and size.");
         }
     }
 }
Esempio n. 12
0
        public static int GetIndex <T>(this IPinnedArray <T> array, int[] indices)
            where T : struct
        {
            if (indices.Length != array.Rank)
            {
                throw new ArgumentException($"Array of length {nameof(array.Rank)} = {array.Rank} expected.", nameof(indices));
            }
            int index = indices[0];

            for (int i = 1; i < indices.Length; i++)
            {
                index *= array.GetLength(i);
                index += indices[i];
            }
            return(index);
        }
Esempio n. 13
0
        public static void CopyTo <T>(this IPinnedArray <T> src, IPinnedArray <T> dst, int[] srcIndices, int[] dstIndices, int count)
            where T : struct
        {
            if (srcIndices == null)
            {
                throw new ArgumentNullException(nameof(srcIndices));
            }
            if (dstIndices == null)
            {
                throw new ArgumentNullException(nameof(dstIndices));
            }

            int srcIndex = src.GetIndex(srcIndices);
            int dstIndex = dst.GetIndex(dstIndices);

            src.CopyTo(dst, srcIndex, dstIndex, count);
        }
Esempio n. 14
0
        static void doBandStop(IPinnedArray <Complex> trans, int[] passIndexRange)
        {
            var j1          = passIndexRange[0];
            var j2          = passIndexRange[1];
            var lenPositive = trans.Length / 2 + trans.Length % 2;

            for (int i = j1; i <= j2; i++)
            {
                trans[i] = 0;
            }

            j1 = trans.Length - j1;
            j2 = trans.Length - j2;
            for (int i = j2; i <= j1; i++)
            {
                trans[i] = 0;
            }
        }
Esempio n. 15
0
 protected override void VerifyRankAndSize(IPinnedArray <double> bufferReal, IPinnedArray <Complex> bufferComplex)
 {
     if (bufferReal.Rank != bufferComplex.Rank)
     {
         throw new ArgumentException($"{nameof(bufferReal)} and {nameof(bufferComplex)} must have the same rank and size.");
     }
     for (int i = 0; i < bufferReal.Rank - 1; i++)
     {
         if (bufferReal.GetLength(i) != bufferComplex.GetLength(i))
         {
             throw new ArgumentException($"Lenght of {nameof(bufferComplex)} must be equal to n[0]*...*(n[n.Length - 1] / 2 + 1) with n being the size of {nameof(bufferReal)}.");
         }
     }
     if (bufferReal.GetLength(bufferReal.Rank - 1) / 2 + 1 != bufferComplex.GetLength(bufferReal.Rank - 1))
     {
         throw new ArgumentException($"Lenght of {nameof(bufferComplex)} must be equal to n[0]*...*(n[n.Length - 1] / 2 + 1) with n being the size of {nameof(bufferReal)}.");
     }
 }
Esempio n. 16
0
        static void Transform(IPinnedArray <Complex> input, IPinnedArray <Complex> output, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
        {
            if ((plannerFlags & PlannerFlags.Estimate) == PlannerFlags.Estimate)
            {
                using (var plan = FftwPlanC2C.Create(input, output, direction, plannerFlags, nThreads))
                {
                    plan.Execute();
                    return;
                }
            }

            using (var plan = FftwPlanC2C.Create(input, output, direction, plannerFlags | PlannerFlags.WisdomOnly, nThreads))
            {
                if (plan != null)
                {
                    plan.Execute();
                    return;
                }
            }

            /// If with <see cref="PlannerFlags.WisdomOnly"/> no plan can be created
            /// and <see cref="PlannerFlags.Estimate"/> is not specified, we use
            /// a different buffer to avoid overwriting the input
            if (input != output)
            {
                using (var plan = FftwPlanC2C.Create(output, output, input.Rank, input.GetSize(), direction, plannerFlags, nThreads))
                {
                    input.CopyTo(output);
                    plan.Execute();
                }
            }
            else
            {
                using (var bufferContainer = _bufferPool.RequestBuffer(input.Length * Marshal.SizeOf <Complex>() + MemoryAlignment))
                    using (var buffer = new AlignedArrayComplex(bufferContainer.Buffer, MemoryAlignment, input.GetSize()))
                        using (var plan = FftwPlanC2C.Create(buffer, buffer, input.Rank, input.GetSize(), direction, plannerFlags, nThreads))
                        {
                            input.CopyTo(plan.Input);
                            plan.Execute();
                            plan.Output.CopyTo(output, 0, 0, input.Length);
                        }
            }
        }
Esempio n. 17
0
        internal protected FftwPlan(IPinnedArray <T1> buffer1, IPinnedArray <T2> buffer2, int rank, int[] n, bool verifyRankAndSize, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
        {
            if (!FftwInterop.IsAvailable)
            {
                throw new InvalidOperationException($"{nameof(FftwInterop.IsAvailable)} returns false.");
            }

            if (buffer1.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(buffer1));
            }
            if (buffer2.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(buffer2));
            }

            if (verifyRankAndSize)
            {
                VerifyRankAndSize(buffer1, buffer2);
            }
            else
            {
                VerifyMinSize(buffer1, buffer2, n);
            }

            if (nThreads < 1)
            {
                nThreads = Environment.ProcessorCount;
            }

            _buffer1 = buffer1;
            _buffer2 = buffer2;
            _plan    = IntPtr.Zero;

            lock (FftwInterop.Lock)
            {
                FftwInterop.fftw_plan_with_nthreads(nThreads);
                _plan = GetPlan(rank, n, _buffer1.Pointer, _buffer2.Pointer, direction, plannerFlags);
            }
        }
Esempio n. 18
0
 FftwPlanC2C(IPinnedArray <Complex> input, IPinnedArray <Complex> output, int rank, int[] n, bool verifyRankAndSize, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
     : base(input, output, rank, n, verifyRankAndSize, direction, plannerFlags, nThreads)
 {
 }
Esempio n. 19
0
 protected abstract void VerifyRankAndSize(IPinnedArray <T1> input, IPinnedArray <T2> output);
Esempio n. 20
0
 /// <summary>
 /// Performs a complex-to-complex inverse fast fourier transformation. The dimension is inferred from the input (<see cref="Array{T}.Rank"/>).
 /// </summary>
 /// <seealso cref="http://www.fftw.org/fftw3_doc/Complex-One_002dDimensional-DFTs.html#Complex-One_002dDimensional-DFTs"/>
 /// <seealso cref="http://www.fftw.org/fftw3_doc/Complex-Multi_002dDimensional-DFTs.html#Complex-Multi_002dDimensional-DFTs"/>
 public static void IFFT(IPinnedArray <Complex> input, IPinnedArray <Complex> output, PlannerFlags plannerFlags = PlannerFlags.Default, int nThreads = 1) => Transform(input, output, DftDirection.Backwards, plannerFlags, nThreads);
Esempio n. 21
0
 FftwPlanRC(IPinnedArray <double> bufferReal, IPinnedArray <Complex> bufferComplex, int rank, int[] n, bool verifyRankAndSize, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
     : base(bufferReal, bufferComplex, rank, n, verifyRankAndSize, direction, plannerFlags, nThreads)
 {
 }
Esempio n. 22
0
 public static void CopyTo <T>(this IPinnedArray <T> src, IPinnedArray <T> dst) where T : struct
 {
     src.CopyTo(dst, 0, 0, dst.Length);
 }
Esempio n. 23
0
 protected abstract void VerifyMinSize(IPinnedArray <T1> ipput, IPinnedArray <T2> output, int[] n);