IPinnedArray.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #region Copyright and License
  2. /*
  3. This file is part of FFTW.NET, a wrapper around the FFTW library for the .NET framework.
  4. Copyright (C) 2017 Tobias Meyer
  5. License: Microsoft Reciprocal License (MS-RL)
  6. */
  7. #endregion
  8. using System;
  9. using System.Runtime.InteropServices;
  10. namespace FFTW.NET
  11. {
  12. public interface IPinnedArray<T> : IDisposable
  13. where T : struct
  14. {
  15. int Rank { get; }
  16. int Length { get; }
  17. IntPtr Pointer { get; }
  18. bool IsDisposed { get; }
  19. int GetLength(int dimension);
  20. int[] GetSize();
  21. T this[params int[] indices] { get; set; }
  22. T this[int i1] { get; set; }
  23. T this[int i1, int i2] { get; set; }
  24. T this[int i1, int i2, int i3] { get; set; }
  25. }
  26. public static class IPinnedArrayExtensions
  27. {
  28. public static void CopyTo<T>(this IPinnedArray<T> src, IPinnedArray<T> dst, int srcIndex, int dstIndex, int count)
  29. where T : struct
  30. {
  31. if (count < 0 || count > src.Length)
  32. throw new ArgumentOutOfRangeException(nameof(count));
  33. if (count > dst.Length)
  34. throw new ArgumentException(nameof(dst), "Destination is not large enough.");
  35. if (srcIndex + count > src.Length)
  36. throw new ArgumentOutOfRangeException(nameof(srcIndex));
  37. if (dstIndex + count > src.Length)
  38. throw new ArgumentOutOfRangeException(nameof(dstIndex));
  39. int sizeOfT = Marshal.SizeOf<T>();
  40. unsafe
  41. {
  42. void* pSrc = new IntPtr(src.Pointer.ToInt64() + srcIndex * sizeOfT).ToPointer();
  43. void* pDst = new IntPtr(dst.Pointer.ToInt64() + dstIndex * sizeOfT).ToPointer();
  44. System.Buffer.MemoryCopy(pSrc, pDst, (long)dst.Length * sizeOfT, (long)count * sizeOfT);
  45. }
  46. }
  47. public static void CopyTo<T>(this IPinnedArray<T> src, IPinnedArray<T> dst, int[] srcIndices, int[] dstIndices, int count)
  48. where T : struct
  49. {
  50. if (srcIndices == null)
  51. throw new ArgumentNullException(nameof(srcIndices));
  52. if (dstIndices == null)
  53. throw new ArgumentNullException(nameof(dstIndices));
  54. int srcIndex = src.GetIndex(srcIndices);
  55. int dstIndex = dst.GetIndex(dstIndices);
  56. src.CopyTo(dst, srcIndex, dstIndex, count);
  57. }
  58. public static void CopyTo<T>(this IPinnedArray<T> src, IPinnedArray<T> dst) where T : struct
  59. {
  60. src.CopyTo(dst, 0, 0, dst.Length);
  61. }
  62. public static int GetIndex<T>(this IPinnedArray<T> array, int[] indices)
  63. where T : struct
  64. {
  65. if (indices.Length != array.Rank)
  66. throw new ArgumentException($"Array of length {nameof(array.Rank)} = {array.Rank} expected.", nameof(indices));
  67. int index = indices[0];
  68. for (int i = 1; i < indices.Length; i++)
  69. {
  70. index *= array.GetLength(i);
  71. index += indices[i];
  72. }
  73. return index;
  74. }
  75. }
  76. }