Skip to content

Commit dfc0745

Browse files
committed
IROTensor,ITensor,Tensor API updates
1 parent 7435fb7 commit dfc0745

File tree

11 files changed

+537
-181
lines changed

11 files changed

+537
-181
lines changed

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs

+112-49
Large diffs are not rendered by default.

src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
</ItemGroup>
1717

1818
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
19+
<Compile Include="System\Numerics\Tensors\netcore\Common\IReadOnlyTensor.cs" />
1920
<Compile Include="System\Numerics\Tensors\netcore\TensorHelpers.cs" />
2021
<Compile Include="System\Numerics\Tensors\netcore\TensorExtensions.cs" />
2122
<Compile Include="System\Numerics\Tensors\netcore\Tensor.Factory.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Buffers;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
11+
namespace System.Numerics.Tensors
12+
{
13+
public interface IReadOnlyTensor<TSelf, T> : IEnumerable<T>
14+
where TSelf : IReadOnlyTensor<TSelf, T>
15+
{
16+
static abstract TSelf? Empty { get; }
17+
18+
bool IsEmpty { get; }
19+
bool IsPinned { get; }
20+
nint FlattenedLength { get; }
21+
int Rank { get; }
22+
23+
T this[params ReadOnlySpan<nint> indexes] { get; }
24+
T this[params ReadOnlySpan<NIndex> indexes] { get; }
25+
TSelf this[params scoped ReadOnlySpan<NRange> ranges] { get; }
26+
27+
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan();
28+
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<nint> start);
29+
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<NIndex> startIndex);
30+
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<NRange> range);
31+
32+
void CopyTo(TensorSpan<T> destination);
33+
void FlattenTo(Span<T> destination);
34+
35+
// These are not properties so that structs can implement the interface without allocating:
36+
void GetLengths(Span<nint> destination);
37+
void GetStrides(Span<nint> destination);
38+
39+
ref readonly T GetPinnableReference();
40+
TSelf Slice(params scoped ReadOnlySpan<nint> start);
41+
TSelf Slice(params scoped ReadOnlySpan<NIndex> startIndex);
42+
TSelf Slice(params scoped ReadOnlySpan<NRange> range);
43+
bool TryCopyTo(TensorSpan<T> destination);
44+
bool TryFlattenTo(Span<T> destination);
45+
}
46+
}

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ITensor.cs

+15-18
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,32 @@
1111
namespace System.Numerics.Tensors
1212
{
1313
public interface ITensor<TSelf, T>
14-
: IEnumerable<T>
14+
: IReadOnlyTensor<TSelf, T>
1515
where TSelf : ITensor<TSelf, T>
1616
{
1717
// TODO: Determine if we can implement `IEqualityOperators<TSelf, T, bool>`.
1818
// It looks like C#/.NET currently hits limitations here as it believes TSelf and T could be the same type
1919
// Ideally we could annotate it such that they cannot be the same type and no conflicts would exist
2020

21-
static abstract TSelf? Empty { get; }
21+
static abstract TSelf Create(ReadOnlySpan<nint> lengths, bool pinned = false);
22+
static abstract TSelf Create(ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides, bool pinned = false);
2223

23-
bool IsEmpty { get; }
24-
bool IsPinned { get; }
25-
int Rank { get; }
26-
nint FlattenedLength { get; }
27-
// THIS IS GOING TO PEND A DISCUSSION WITH THE LANGUAGE TEAM
28-
void GetStrides(Span<nint> destination);
29-
void GetLengths(Span<nint> destination);
24+
static abstract TSelf CreateUninitialized(ReadOnlySpan<nint> lengths, bool pinned = false);
25+
static abstract TSelf CreateUninitialized(ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides, bool pinned = false);
3026

31-
T this[params scoped ReadOnlySpan<nint> indexes] { get; }
32-
T this[params scoped ReadOnlySpan<NIndex> indexes] { get; set; }
33-
TSelf this[params scoped ReadOnlySpan<NRange> ranges] { get; set; }
27+
bool IsReadOnly { get; }
3428

35-
TensorSpan<T> AsTensorSpan(params scoped ReadOnlySpan<NRange> ranges);
36-
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<NRange> ranges);
37-
ref T GetPinnableReference();
38-
TSelf Slice(params scoped ReadOnlySpan<NRange> ranges);
29+
new T this[params ReadOnlySpan<nint> indexes] { get; set; }
30+
new T this[params ReadOnlySpan<NIndex> indexes] { get; set; }
31+
new TSelf this[params scoped ReadOnlySpan<NRange> ranges] { get; set; }
32+
33+
TensorSpan<T> AsTensorSpan();
34+
TensorSpan<T> AsTensorSpan(params scoped ReadOnlySpan<nint> start);
35+
TensorSpan<T> AsTensorSpan(params scoped ReadOnlySpan<NIndex> startIndex);
36+
TensorSpan<T> AsTensorSpan(params scoped ReadOnlySpan<NRange> range);
3937

4038
void Clear();
41-
void CopyTo(TensorSpan<T> destination);
4239
void Fill(T value);
43-
bool TryCopyTo(TensorSpan<T> destination);
40+
new ref T GetPinnableReference();
4441
}
4542
}

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public ReadOnlyTensorSpan(T[]? array) : this(array, 0, default, default)
5656
/// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
5757
/// <exception cref="ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
5858
/// <exception cref="ArgumentOutOfRangeException">
59-
/// Thrown when the specified <paramref name="startIndex"/> or end index is not in the range (&lt;0 or &gt;Length).
59+
/// Thrown when the specified <paramref name="startIndex"/> or end index is not in the range (&lt;0 or &gt;FlattenedLength).
6060
/// </exception>
6161
public ReadOnlyTensorSpan(T[]? array, Index startIndex, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides)
6262
: this(array, startIndex.GetOffset(array?.Length ?? 0), lengths, strides)
@@ -74,7 +74,7 @@ public ReadOnlyTensorSpan(T[]? array, Index startIndex, ReadOnlySpan<nint> lengt
7474
/// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
7575
/// <exception cref="ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
7676
/// <exception cref="ArgumentOutOfRangeException">
77-
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;Length).
77+
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;FlattenedLength).
7878
/// </exception>
7979
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8080
public ReadOnlyTensorSpan(T[]? array, int start, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides)
@@ -205,7 +205,7 @@ internal ReadOnlyTensorSpan(ref T reference, scoped ReadOnlySpan<nint> lengths,
205205
/// <param name="indexes"></param>
206206
/// <returns></returns>
207207
/// <exception cref="IndexOutOfRangeException">
208-
/// Thrown when any index is less than 0 or any index is greater than or equal to Length
208+
/// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength
209209
/// </exception>
210210
public ref readonly T this[params scoped ReadOnlySpan<nint> indexes]
211211
{
@@ -229,7 +229,7 @@ public ref readonly T this[params scoped ReadOnlySpan<nint> indexes]
229229
/// <param name="indexes"></param>
230230
/// <returns></returns>
231231
/// <exception cref="IndexOutOfRangeException">
232-
/// Thrown when any index is less than 0 or any index is greater than or equal to Length
232+
/// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength
233233
/// </exception>
234234
public ref readonly T this[params scoped ReadOnlySpan<NIndex> indexes]
235235
{
@@ -252,7 +252,7 @@ public ref readonly T this[params scoped ReadOnlySpan<NIndex> indexes]
252252
/// <param name="ranges"></param>
253253
/// <returns></returns>
254254
/// <exception cref="IndexOutOfRangeException">
255-
/// Thrown when any index is less than 0 or any index is greater than or equal to Length
255+
/// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength
256256
/// </exception>
257257
public ReadOnlyTensorSpan<T> this[params scoped ReadOnlySpan<NRange> ranges]
258258
{
@@ -515,7 +515,7 @@ public bool TryCopyTo(TensorSpan<T> destination)
515515
/// <param name="indexes">The indexes for the slice.</param>
516516
/// <returns></returns>
517517
/// <exception cref="IndexOutOfRangeException">
518-
/// Thrown when any index is less than 0 or any index is greater than or equal to Length
518+
/// Thrown when any index is less than 0 or any index is greater than or equal to FlattenedLength
519519
/// </exception>
520520
public ReadOnlyTensorSpan<T> Slice(params scoped ReadOnlySpan<NIndex> indexes)
521521
{

src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs

+20-20
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,30 @@ namespace System.Numerics.Tensors
1313
public static partial class Tensor
1414
{
1515
/// <summary>
16-
/// Creates a <see cref="Tensor{T}"/> and initializes it with the default value of T. If <paramref name="mustPin"/> is true, the memory will be pinned.
16+
/// Creates a <see cref="Tensor{T}"/> and initializes it with the default value of T. If <paramref name="pinned"/> is true, the memory will be pinned.
1717
/// </summary>
18-
/// <param name="mustPin">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
1918
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
20-
public static Tensor<T> Create<T>(bool mustPin, ReadOnlySpan<nint> lengths)
19+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
20+
public static Tensor<T> Create<T>(ReadOnlySpan<nint> lengths, bool pinned = false)
2121
where T : IEquatable<T>
2222
{
2323
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
24-
T[] values = mustPin ? GC.AllocateArray<T>((int)linearLength, mustPin) : (new T[linearLength]);
25-
return new Tensor<T>(values, lengths.ToArray(), mustPin);
24+
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
25+
return new Tensor<T>(values, lengths.ToArray(), pinned);
2626
}
2727

2828
/// <summary>
29-
/// Creates a <see cref="Tensor{T}"/> and initializes it with the default value of T. If <paramref name="mustPin"/> is true, the memory will be pinned.
29+
/// Creates a <see cref="Tensor{T}"/> and initializes it with the default value of T. If <paramref name="pinned"/> is true, the memory will be pinned.
3030
/// </summary>
31-
/// <param name="mustPin">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
3231
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
3332
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
34-
public static Tensor<T> Create<T>(bool mustPin, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides)
33+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
34+
public static Tensor<T> Create<T>(ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides, bool pinned = false)
3535
where T : IEquatable<T>
3636
{
3737
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
38-
T[] values = mustPin ? GC.AllocateArray<T>((int)linearLength, mustPin) : (new T[linearLength]);
39-
return new Tensor<T>(values, lengths.ToArray(), strides.ToArray(), mustPin);
38+
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
39+
return new Tensor<T>(values, lengths.ToArray(), strides.ToArray(), pinned);
4040
}
4141

4242
/// <summary>
@@ -75,30 +75,30 @@ public static Tensor<T> Create<T>(T[] values, ReadOnlySpan<nint> lengths, ReadOn
7575
}
7676

7777
/// <summary>
78-
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="mustPin"/> is true, the memory will be pinned.
78+
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
7979
/// </summary>
80-
/// <param name="mustPin">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
8180
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
82-
public static Tensor<T> CreateUninitialized<T>(bool mustPin, ReadOnlySpan<nint> lengths)
81+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
82+
public static Tensor<T> CreateUninitialized<T>(ReadOnlySpan<nint> lengths, bool pinned = false)
8383
where T : IEquatable<T>
8484
{
8585
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
86-
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, mustPin);
87-
return new Tensor<T>(values, lengths.ToArray(), mustPin);
86+
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
87+
return new Tensor<T>(values, lengths.ToArray(), pinned);
8888
}
8989

9090
/// <summary>
91-
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="mustPin"/> is true, the memory will be pinned.
91+
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
9292
/// </summary>
93-
/// <param name="mustPin">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
9493
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
9594
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
96-
public static Tensor<T> CreateUninitialized<T>(bool mustPin, ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides)
95+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
96+
public static Tensor<T> CreateUninitialized<T>(ReadOnlySpan<nint> lengths, ReadOnlySpan<nint> strides, bool pinned = false )
9797
where T : IEquatable<T>
9898
{
9999
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
100-
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, mustPin);
101-
return new Tensor<T>(values, lengths.ToArray(), strides.ToArray(), mustPin);
100+
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
101+
return new Tensor<T>(values, lengths.ToArray(), strides.ToArray(), pinned);
102102
}
103103

104104
/// <summary>

0 commit comments

Comments
 (0)