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); }
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) { }
/// <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); }
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); }
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) { }
protected override IntPtr GetPlan(int rank, int[] n, IntPtr input, IntPtr output, DftDirection direction, PlannerFlags plannerFlags) { return(FftwInterop.fftw_plan_dft(rank, n, input, output, direction, plannerFlags)); }
static extern IntPtr fftw_plan_dft_c2r_ARM(int rank, [MarshalAs(UnmanagedType.LPArray)] int[] n, IntPtr arrIn, IntPtr arrOut, PlannerFlags flags);
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); } }
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); } } }
static extern IntPtr fftw_plan_dft_x64(int rank, [MarshalAs(UnmanagedType.LPArray)] int[] n, IntPtr arrIn, IntPtr arrOut, DftDirection direction, PlannerFlags flags);
/// <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);
/// <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(); } }
protected abstract IntPtr GetPlan(int rank, int[] n, IntPtr input, IntPtr output, DftDirection direction, PlannerFlags plannerFlags);
protected override IntPtr GetPlan(int rank, int[] n, IntPtr bufferReal, IntPtr bufferComplex, DftDirection direction, PlannerFlags plannerFlags) { if (direction == DftDirection.Forwards) { return(FftwInterop.fftw_plan_dft_r2c(rank, n, bufferReal, bufferComplex, plannerFlags)); } else { return(FftwInterop.fftw_plan_dft_c2r(rank, n, bufferComplex, bufferReal, plannerFlags)); } }
public static IntPtr fftw_plan_dft_c2r(int rank, [MarshalAs(UnmanagedType.LPArray)] int[] n, IntPtr arrIn, IntPtr arrOut, PlannerFlags flags) { if (RuntimeInformation.ProcessArchitecture == Architecture.X64) { return(fftw_plan_dft_c2r_x64(rank, n, arrIn, arrOut, flags)); } else if (RuntimeInformation.ProcessArchitecture == Architecture.X86) { return(fftw_plan_dft_c2r_x86(rank, n, arrIn, arrOut, flags)); } else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm) { return(fftw_plan_dft_c2r_ARM(rank, n, arrIn, arrOut, flags)); } else { throw new PlatformNotSupportedException(); } }
/// <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); }
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); //} }