#region Copyright and License /* This file is part of FFTW.NET, a wrapper around the FFTW library for the .NET framework. Copyright (C) 2017 Tobias Meyer License: Microsoft Reciprocal License (MS-RL) */ #endregion using System; using System.Runtime.InteropServices; namespace FFTW.NET { /// /// Wrapper around which provides some level of type-safety. /// If you have access to the strongly typed instance of the underlying buffer (e.g. T[], T[,], T[,,], etc.) /// you should always get and set values using the strongly typed instance. /// uses / internally which is much slower than /// using the strongly typed instance directly. /// public class PinnedArray : IPinnedArray where T : struct { readonly System.Array _buffer; readonly PinnedGCHandle _pin; public int Rank => _buffer.Rank; public Array Buffer => _buffer; public int Length => _buffer.Length; public IntPtr Pointer => _pin.Pointer; public bool IsDisposed => !_pin.IsAllocated; public PinnedArray(params int[] lengths) : this(Array.CreateInstance(typeof(T), lengths)) { } public PinnedArray(Array array) { if (array.GetType().GetElementType() != typeof(T)) throw new ArgumentException($"Must have elements of type {typeof(T).FullName}.", nameof(array)); _buffer = array; _pin = PinnedGCHandle.Pin(_buffer); } public int GetLength(int dimension) => _buffer.GetLength(dimension); public int[] GetSize() { int[] result = new int[Rank]; for (int i = 0; i < Rank; i++) result[i] = GetLength(i); return result; } public T this[params int[] indices] { get { return (T)_buffer.GetValue(indices)!; } set { _buffer.SetValue(value, indices); } } public T this[int index] { get { return (T)_buffer.GetValue(index)!; } set { _buffer.SetValue(value, index); } } public T this[int i1, int i2] { get { return (T)_buffer.GetValue(i1, i2)!; } set { _buffer.SetValue(value, i1, i2); } } public T this[int i1, int i2, int i3] { get { return (T)_buffer.GetValue(i1, i2, i3)!; } set { _buffer.SetValue(value, i1, i2, i3); } } public static implicit operator Array(PinnedArray array) => array._buffer; public static explicit operator PinnedArray(Array array) => new PinnedArray(array); public void Dispose() => _pin.Free(); } }