public void CopyToArray(Array array) { var elementType = DTypeBuilder.FromCLRType(array.GetType().GetElementType()); if (!this.IsContiguous()) { throw new InvalidOperationException("Tensor must be contiguous to copy from CLR array"); } if (this.ElementCount() != array.LongLength) { throw new InvalidOperationException("Tensor and array must have the same number of elements"); } if (this.ElementType != elementType) { throw new InvalidOperationException("Tensor and array must have the same element types"); } var handle = GCHandle.Alloc(array, GCHandleType.Pinned); try { var length = Buffer.ByteLength(array); this.Storage.CopyFromStorage(handle.AddrOfPinnedObject(), this.StorageOffset, length); } finally { handle.Free(); } }
public static Tensor FromArray(IAllocator allocator, Array array) { // From the CLI spec(section 8.9.1): // Array elements shall be laid out within the array object in row - major order // (i.e., the elements associated with the rightmost array dimension shall be laid out contiguously from lowest to highest index). // The actual storage allocated for each array element can include platform - specific padding. // This is already in the order we want - and here we will (potentially incorrectly) assume that there is no // 'platform-specific padding'. This appears to be a reasonable assumption on both CLR and Mono. // Assuming no platform-specific padding allows us to use memcpy instead of iterating and copying each element var elementType = DTypeBuilder.FromCLRType(array.GetType().GetElementType()); var dimSizes = Enumerable.Range(0, array.Rank).Select(x => (long)array.GetLength(x)).ToArray(); var result = new Tensor(allocator, elementType, dimSizes); result.CopyFrom(array); return(result); }