FftwArray.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. using System.Runtime.InteropServices;
  19. namespace FFTW.NET
  20. {
  21. public class FftwArray<T> : IPinnedArray<T>
  22. where T : struct
  23. {
  24. readonly int[] _lengths;
  25. IntPtr _ptr;
  26. public FftwArray(params int[] lengths)
  27. {
  28. _lengths = lengths;
  29. long size = LongLength * Marshal.SizeOf<T>();
  30. _ptr =FftwInterop.GetDelegate<FftwInterop.fftw_malloc>()(new IntPtr(size));
  31. GC.AddMemoryPressure(size);
  32. }
  33. public int Length
  34. {
  35. get
  36. {
  37. checked
  38. {
  39. int value = 1;
  40. foreach (var n in _lengths)
  41. value *= n;
  42. return value;
  43. }
  44. }
  45. }
  46. public long LongLength
  47. {
  48. get
  49. {
  50. long value = 1;
  51. foreach (var n in _lengths)
  52. value *= n;
  53. return value;
  54. }
  55. }
  56. public IntPtr Pointer => _ptr;
  57. public int Rank => _lengths.Length;
  58. public bool IsDisposed => _ptr == IntPtr.Zero;
  59. public void Dispose()
  60. {
  61. if (_ptr == IntPtr.Zero)
  62. return;
  63. FftwInterop.GetDelegate<FftwInterop.fftw_free>()(_ptr);
  64. _ptr = IntPtr.Zero;
  65. GC.RemoveMemoryPressure(LongLength * Marshal.SizeOf<T>());
  66. }
  67. public int GetLength(int dimension) => _lengths[dimension];
  68. public int[] GetSize()
  69. {
  70. int[] result = new int[Rank];
  71. Buffer.BlockCopy(_lengths, 0, result, 0, Rank * sizeof(int));
  72. return result;
  73. }
  74. protected virtual T GetCore(IntPtr ptr) => Marshal.PtrToStructure<T>(ptr);
  75. protected virtual void SetCore(T value, IntPtr ptr) => Marshal.StructureToPtr<T>(value, ptr, false);
  76. void VerifyRank(int rank)
  77. {
  78. if (rank != this.Rank)
  79. throw new InvalidOperationException($"Dimension mismatch: Rank is not {Rank}");
  80. }
  81. void VerifyNotDisposed()
  82. {
  83. if (_ptr == IntPtr.Zero)
  84. throw new ObjectDisposedException(this.GetType().FullName);
  85. }
  86. public T this[int i1]
  87. {
  88. get
  89. {
  90. VerifyNotDisposed();
  91. VerifyRank(1);
  92. var ptr = this.Pointer + (i1 * Marshal.SizeOf<T>());
  93. return GetCore(ptr);
  94. }
  95. set
  96. {
  97. VerifyNotDisposed();
  98. VerifyRank(1);
  99. var ptr = this.Pointer + (i1 * Marshal.SizeOf<T>());
  100. SetCore(value, ptr);
  101. }
  102. }
  103. public T this[int i1, int i2]
  104. {
  105. get
  106. {
  107. VerifyNotDisposed();
  108. VerifyRank(2);
  109. var ptr = this.Pointer + (i2 + GetLength(1) * i1) * Marshal.SizeOf<T>();
  110. return GetCore(ptr);
  111. }
  112. set
  113. {
  114. VerifyNotDisposed();
  115. VerifyRank(2);
  116. var ptr = this.Pointer + (i2 + GetLength(1) * i1) * Marshal.SizeOf<T>();
  117. SetCore(value, ptr);
  118. }
  119. }
  120. public T this[int i1, int i2, int i3]
  121. {
  122. get
  123. {
  124. VerifyNotDisposed();
  125. VerifyRank(3);
  126. var ptr = this.Pointer + (i3 + GetLength(2) * (i2 + GetLength(1) * i1)) * Marshal.SizeOf<T>();
  127. return GetCore(ptr);
  128. }
  129. set
  130. {
  131. VerifyNotDisposed();
  132. VerifyRank(3);
  133. var ptr = this.Pointer + (i3 + GetLength(2) * (i2 + GetLength(1) * i1)) * Marshal.SizeOf<T>();
  134. SetCore(value, ptr);
  135. }
  136. }
  137. public T this[params int[] indices]
  138. {
  139. get
  140. {
  141. VerifyNotDisposed();
  142. VerifyRank(indices.Length);
  143. var ptr = new IntPtr(this.Pointer.ToInt64() + this.GetIndex(indices));
  144. return GetCore(ptr);
  145. }
  146. set
  147. {
  148. VerifyNotDisposed();
  149. VerifyRank(indices.Length);
  150. var ptr = new IntPtr(this.Pointer.ToInt64() + this.GetIndex(indices));
  151. SetCore(value, ptr);
  152. }
  153. }
  154. }
  155. public class FftwArrayComplex : FftwArray<Complex>
  156. {
  157. public FftwArrayComplex(params int[] lengths)
  158. : base(lengths) { }
  159. protected unsafe override Complex GetCore(IntPtr ptr) => *((Complex*)ptr.ToPointer());
  160. protected unsafe override void SetCore(Complex value, IntPtr ptr) => *((Complex*)ptr.ToPointer()) = value;
  161. }
  162. public class FftwArrayDouble : FftwArray<double>
  163. {
  164. public FftwArrayDouble(params int[] lengths)
  165. : base(lengths) { }
  166. protected unsafe override double GetCore(IntPtr ptr) => *((double*)ptr.ToPointer());
  167. protected unsafe override void SetCore(double value, IntPtr ptr) => *((double*)ptr.ToPointer()) = value;
  168. }
  169. }