FftwPlan.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #region Copyright and License
  2. /*
  3. This file is part of FFTW.NET, a wrapper around the FFTW library
  4. for the .NET framework.
  5. Copyright (C) 2017 Tobias Meyer
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. */
  15. #endregion
  16. using System;
  17. using System.Numerics;
  18. namespace FFTW.NET
  19. {
  20. public abstract class FftwPlan<T1, T2> : IDisposable
  21. where T1 : struct
  22. where T2 : struct
  23. {
  24. IntPtr _plan = IntPtr.Zero;
  25. readonly IPinnedArray<T1> _buffer1;
  26. readonly IPinnedArray<T2> _buffer2;
  27. protected IPinnedArray<T1> Buffer1 => _buffer1;
  28. protected IPinnedArray<T2> Buffer2 => _buffer2;
  29. internal protected bool IsZero => _plan == IntPtr.Zero;
  30. internal protected FftwPlan(IPinnedArray<T1> buffer1, IPinnedArray<T2> buffer2, int rank, int[] n, bool verifyRankAndSize, DftDirection direction, PlannerFlags plannerFlags, int nThreads)
  31. {
  32. if (!FftwInterop.IsAvailable)
  33. throw new InvalidOperationException($"{nameof(FftwInterop.IsAvailable)} returns false.");
  34. if (buffer1.IsDisposed)
  35. throw new ObjectDisposedException(nameof(buffer1));
  36. if (buffer2.IsDisposed)
  37. throw new ObjectDisposedException(nameof(buffer2));
  38. if (verifyRankAndSize)
  39. VerifyRankAndSize(buffer1, buffer2);
  40. else
  41. VerifyMinSize(buffer1, buffer2, n);
  42. if (nThreads < 1)
  43. nThreads = Environment.ProcessorCount;
  44. _buffer1 = buffer1;
  45. _buffer2 = buffer2;
  46. _plan = IntPtr.Zero;
  47. lock (FftwInterop.Lock)
  48. {
  49. //FftwInterop.GetDelegate<FftwInterop.fftw_plan_with_nthreads>()(nThreads);
  50. _plan = GetPlan(rank, n, _buffer1.Pointer, _buffer2.Pointer, direction, plannerFlags);
  51. }
  52. }
  53. protected abstract IntPtr GetPlan(int rank, int[] n, IntPtr input, IntPtr output, DftDirection direction, PlannerFlags plannerFlags);
  54. protected abstract void VerifyRankAndSize(IPinnedArray<T1> input, IPinnedArray<T2> output);
  55. protected abstract void VerifyMinSize(IPinnedArray<T1> ipput, IPinnedArray<T2> output, int[] n);
  56. public void Execute()
  57. {
  58. if (_plan == IntPtr.Zero)
  59. throw new ObjectDisposedException(this.GetType().FullName);
  60. FftwInterop.GetDelegate<FftwInterop.fftw_execute>()(_plan);
  61. }
  62. public void Dispose()
  63. {
  64. if (_plan == IntPtr.Zero)
  65. return;
  66. lock (FftwInterop.Lock)
  67. {
  68. if (_plan == IntPtr.Zero)
  69. return;
  70. FftwInterop.GetDelegate<FftwInterop.fftw_destroy_plan>()(_plan);
  71. _plan = IntPtr.Zero;
  72. }
  73. }
  74. }
  75. }