/// <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(); } }
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); } } }
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); }
public static void CopyTo <T>(this IPinnedArray <T> src, IPinnedArray <T> dst) where T : struct { src.CopyTo(dst, 0, 0, dst.Length); }