Skip to content

Commit 49efa9b

Browse files
github-actions[bot]tannergoodingmichaelgsharp
authored
[release/10.0-preview4] Rewrite of System.Numerics.Tensors to allow for more code sharing, various correctness fixes, and stability improvements (#114979)
* Refactor Tensor to be more reusable and validate appropriate state * Handle Equals, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual, and the *All/*Any variants * Many implementations correctly swapped to new form. (#25) * Refactor Tensor to be more reusable and validate appropriate state * finishing tensor primitives work --------- Co-authored-by: Tanner Gooding <[email protected]> * more tensors updates (#26) * Resolve a few build failures * Ensure SetSlice and ToString are working as expected * Tensors lastfew (#27) * only couple left * pausing for food * fixed rented buffer * squeeze/unsqueeze * set slice/ split * only 2 left * Minor cleanup of the Tensor files * Ensure that tensor tests are building * Resolving various build failures due to API compatibility * Ensure flattendLength is adjusted after the stride is set for that dimension * Ensure that we set linearLength if -1 is passed in when strides is empty * Ensure that the first index is correct * Cleanup to ensure iteration and construction initializes correctly * Ensure that broadcasting is allowed to be in any stride position * Have AreCompatible handle empty shapes * Ensure IndexOutOfRangeException is thrown for invalid indexes * Ensure that the stride is set to 0 when the length of a dimension is 1, so embedded broadcasting works * Fixing Broadcasting Loop (#29) * Fixing Broadcasting Loop * fixes from pr coments * squeeze fixed * unsqueeze * set slice * more tensor fies * Ensure that minimumLinearLength is actually the minimum * Ensure the rented buffer is cleared * Fix the AreCompatible checks * Tensor finishing (#30) * stack working * more tensor tests working * fix factory create tests * only2 tests left * Update src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs * Update compatibility suppressions * transpose working * reverse working * Revert the unnecessary sln changes * Remove an unnecessary using --------- Co-authored-by: Tanner Gooding <[email protected]> Co-authored-by: Michael Sharp <[email protected]> Co-authored-by: Michael Sharp <[email protected]>
1 parent 1e69c98 commit 49efa9b

26 files changed

+12027
-11040
lines changed

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

Lines changed: 96 additions & 59 deletions
Large diffs are not rendered by default.

src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml

Lines changed: 560 additions & 0 deletions
Large diffs are not rendered by default.

src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@
201201
<data name="ThrowArgument_SetSliceNoRange" xml:space="preserve">
202202
<value>When no ranges are specified the values tensor must be equal in size as the input tensor.</value>
203203
</data>
204-
<data name="ThrowArgument_LengthsNotBroadcastCompatible" xml:space="preserve">
205-
<value>Lengths are not broadcast compatible.</value>
204+
<data name="ThrowArgument_LengthsNotCompatible" xml:space="preserve">
205+
<value>Lengths are not compatible with each other.</value>
206206
</data>
207207
<data name="ThrowArgument_SplitNotSplitEvenly" xml:space="preserve">
208208
<value>The number of splits must perfectly divide the dimension.</value>
@@ -240,4 +240,7 @@
240240
<data name="Arithmetic_NaN" xml:space="preserve">
241241
<value>Function does not accept floating point Not-a-Number values.</value>
242242
</data>
243-
</root>
243+
<data name="ThrowArgument_LengthIsNonZeroForNullReference" xml:space="preserve">
244+
<value>The provided length is non zero while the data reference is null.</value>
245+
</data>
246+
</root>

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

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,8 @@
1919
</ItemGroup>
2020

2121
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
22-
<Compile Include="System\Numerics\Tensors\netcore\TensorShape.cs" />
23-
<Compile Include="System\Numerics\Tensors\netcore\TensorHelpers.cs" />
24-
<Compile Include="System\Numerics\Tensors\netcore\TensorExtensions.cs" />
25-
<Compile Include="System\Numerics\Tensors\netcore\Tensor.Factory.cs" />
26-
<Compile Include="System\Numerics\Tensors\netcore\Tensor.cs" />
27-
<Compile Include="System\Numerics\Tensors\netcore\ITensor.cs" />
28-
<Compile Include="System\Numerics\Tensors\netcore\IReadOnlyTensor.cs" />
29-
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanDebugView.cs" />
30-
<Compile Include="System\Numerics\Tensors\netcore\ReadOnlyTensorSpan.cs" />
31-
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.cs" />
32-
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.T.cs" />
33-
<Compile Include="System\Numerics\Tensors\netcore\TensorSpan.cs" />
34-
<Compile Include="System\NIndex.cs" />
35-
<Compile Include="System\NRange.cs" />
22+
<Compile Include="System\Buffers\NIndex.cs" />
23+
<Compile Include="System\Buffers\NRange.cs" />
3624
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IAggregationOperator.cs" />
3725
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IBinaryOperator.cs" />
3826
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IBooleanUnaryOperator.cs" />
@@ -44,6 +32,14 @@
4432
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IUnaryOneToFourOperator.cs" />
4533
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IUnaryOperator.cs" />
4634
<Compile Include="System\Numerics\Tensors\netcore\Common\TensorPrimitives.IUnaryTwoToOneOperator.cs" />
35+
<Compile Include="System\Numerics\Tensors\netcore\IReadOnlyTensor.cs" />
36+
<Compile Include="System\Numerics\Tensors\netcore\IReadOnlyTensor_1.cs" />
37+
<Compile Include="System\Numerics\Tensors\netcore\ITensor.cs" />
38+
<Compile Include="System\Numerics\Tensors\netcore\ITensor_1.cs" />
39+
<Compile Include="System\Numerics\Tensors\netcore\ReadOnlyTensorSpan_1.cs" />
40+
<Compile Include="System\Numerics\Tensors\netcore\Tensor.cs" />
41+
<Compile Include="System\Numerics\Tensors\netcore\Tensor_1.cs" />
42+
<Compile Include="System\Numerics\Tensors\netcore\TensorOperation.cs" />
4743
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Abs.cs" />
4844
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Acos.cs" />
4945
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Acosh.cs" />
@@ -170,6 +166,9 @@
170166
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.TrailingZeroCount.cs" />
171167
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Truncate.cs" />
172168
<Compile Include="System\Numerics\Tensors\netcore\TensorPrimitives.Xor.cs" />
169+
<Compile Include="System\Numerics\Tensors\netcore\TensorShape.cs" />
170+
<Compile Include="System\Numerics\Tensors\netcore\TensorSpan.cs" />
171+
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanDebugView.cs" />
173172
</ItemGroup>
174173

175174
<ItemGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net9.0'))">

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

Lines changed: 26 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -2,181 +2,50 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Buffers;
5-
using System.Collections.Generic;
65
using System.Diagnostics.CodeAnalysis;
76

87
namespace System.Numerics.Tensors
98
{
10-
11-
/// <summary>
12-
/// Represents a read-only tensor.
13-
/// </summary>
9+
/// <summary>Represents a read-only tensor.</summary>
1410
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
1511
public interface IReadOnlyTensor
1612
{
17-
/// <summary>
18-
/// Gets a value that indicates whether the collection is currently empty.
19-
/// </summary>
13+
/// <summary>Gets the specified element of the tensor.</summary>
14+
/// <param name="indexes">The index of the element for which to get.</param>
15+
/// <returns>The element that exists at <paramref name="indexes" />.</returns>
16+
/// <exception cref="ArgumentOutOfRangeException">
17+
/// Thrown when one of the following conditions is met:
18+
/// * <paramref name="indexes" /> does not contain <see cref="Rank" /> elements
19+
/// * <paramref name="indexes" /> contains an element that is negative or greater than or equal to the corresponding dimension length
20+
/// </exception>
21+
object? this[params scoped ReadOnlySpan<nint> indexes] { get; }
22+
23+
/// <inheritdoc cref="this[ReadOnlySpan{nint}]" />
24+
object? this[params scoped ReadOnlySpan<NIndex> indexes] { get; }
25+
26+
/// <summary>Gets the total number of items in the tensor.</summary>
27+
nint FlattenedLength { get; }
28+
29+
/// <summary>Gets a value indicating whether this tensor is empty.</summary>
30+
/// <value><see langword="true"/> if this tensor is empty; otherwise, <see langword="false"/>.</value>
2031
bool IsEmpty { get; }
2132

22-
/// <summary>
23-
/// Gets a value that indicates whether the underlying buffer is pinned.
24-
/// </summary>
33+
/// <summary>Gets a value that indicates whether the underlying buffer is pinned.</summary>
2534
bool IsPinned { get; }
2635

27-
/// <summary>
28-
/// Gets the number of elements in the tensor.
29-
/// </summary>
30-
nint FlattenedLength { get; }
31-
32-
/// <summary>
33-
/// Gets the number of dimensions in the tensor.
34-
/// </summary>
35-
int Rank { get; }
36-
37-
/// <summary>
38-
/// Gets the length of each dimension in the tensor.
39-
/// </summary>
36+
/// <summary>Gets the length of each dimension in the tensor.</summary>
4037
[UnscopedRef]
4138
ReadOnlySpan<nint> Lengths { get; }
4239

43-
/// <summary>
44-
/// Gets the stride of each dimension in the tensor.
45-
/// </summary>
40+
/// <summary>Gets the rank, or number of dimensions, in the tensor.</summary>
41+
int Rank { get; }
42+
43+
/// <summary>Gets the stride of each dimension in the tensor.</summary>
4644
[UnscopedRef]
4745
ReadOnlySpan<nint> Strides { get; }
4846

49-
/// <summary>
50-
/// Gets the value at the specified indexes.
51-
/// </summary>
52-
/// <param name="indexes">The indexes to be used.</param>
53-
object this[params scoped ReadOnlySpan<nint> indexes] { get; }
54-
55-
/// <summary>
56-
/// Gets the value at the specified indexes.
57-
/// </summary>
58-
/// <param name="indexes">The indexes to be used.</param>
59-
object this[params scoped ReadOnlySpan<NIndex> indexes] { get; }
60-
61-
/// <summary>
62-
/// Pins and gets a <see cref="MemoryHandle"/> to the backing memory.
63-
/// </summary>
47+
/// <summary>Pins and gets a <see cref="MemoryHandle"/> to the backing memory.</summary>
6448
/// <returns><see cref="MemoryHandle"/></returns>
6549
MemoryHandle GetPinnedHandle();
6650
}
67-
68-
/// <summary>
69-
/// Represents a read-only tensor.
70-
/// </summary>
71-
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
72-
/// <typeparam name="T">The element type.</typeparam>
73-
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
74-
public interface IReadOnlyTensor<TSelf, T> : IReadOnlyTensor, IEnumerable<T>
75-
where TSelf : IReadOnlyTensor<TSelf, T>
76-
{
77-
/// <summary>
78-
/// Gets an empty tensor.
79-
/// </summary>
80-
static abstract TSelf? Empty { get; }
81-
82-
/// <summary>
83-
/// Gets the value at the specified indexes.
84-
/// </summary>
85-
/// <param name="indexes">The indexes to be used.</param>
86-
new T this[params scoped ReadOnlySpan<nint> indexes] { get; }
87-
88-
/// <summary>
89-
/// Gets the value at the specified indexes.
90-
/// </summary>
91-
/// <param name="indexes">The indexes to be used.</param>
92-
new T this[params scoped ReadOnlySpan<NIndex> indexes] { get; }
93-
94-
/// <summary>
95-
/// Gets the values at the specified ranges.
96-
/// </summary>
97-
/// <param name="ranges">The ranges to be used.</param>
98-
TSelf this[params scoped ReadOnlySpan<NRange> ranges] { get; }
99-
100-
/// <summary>
101-
/// Creates a read-only tensor span for the entire underlying buffer.
102-
/// </summary>
103-
/// <returns>The converted <see cref="ReadOnlyTensorSpan{T}"/>.</returns>
104-
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan();
105-
106-
/// <summary>
107-
/// Creates a read-only tensor span for the specified start indexes.
108-
/// </summary>
109-
/// <param name="start">The start locations to be used.</param>
110-
/// <returns>The converted <see cref="ReadOnlyTensorSpan{T}"/>.</returns>
111-
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<nint> start);
112-
113-
/// <summary>
114-
/// Creates a read-only tensor span for the specified start indexes.
115-
/// </summary>
116-
/// <param name="startIndex">The started indexes to be used.</param>
117-
/// <returns>The converted <see cref="ReadOnlyTensorSpan{T}"/>.</returns>
118-
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<NIndex> startIndex);
119-
120-
/// <summary>
121-
/// Creates a read-only tensor span for the specified ranges.
122-
/// </summary>
123-
/// <param name="range">The ranges to be used.</param>
124-
/// <returns>The converted <see cref="ReadOnlyTensorSpan{T}"/>.</returns>
125-
ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped ReadOnlySpan<NRange> range);
126-
127-
/// <summary>
128-
/// Copies the tensor to the specified destination. The destination tensor must be equal to or larger than the source tensor.
129-
/// </summary>
130-
/// <param name="destination">The destination span where the data should be copied to.</param>
131-
void CopyTo(scoped TensorSpan<T> destination);
132-
133-
/// <summary>
134-
/// Flattens the tensor to the specified destination. The destination span must be equal to or larger than the number of elements in the source tensor.
135-
/// </summary>
136-
/// <param name="destination">The destination span where the data should be flattened to.</param>
137-
void FlattenTo(scoped Span<T> destination);
138-
139-
/// <summary>
140-
/// Returns a reference to the 0th element of the tensor. If the tensor is empty, returns <see langword="null"/>.
141-
/// </summary>
142-
/// <remarks>
143-
/// This method can be used for pinning and is required to support the use of the tensor within a fixed statement.
144-
/// </remarks>
145-
ref readonly T GetPinnableReference();
146-
147-
/// <summary>
148-
/// Slices the tensor using the specified start indexes.
149-
/// </summary>
150-
/// <param name="start">The start locations to be used.</param>
151-
/// <returns>The sliced tensor.</returns>
152-
TSelf Slice(params scoped ReadOnlySpan<nint> start);
153-
154-
/// <summary>
155-
/// Slices the tensor using the specified start indexes.
156-
/// </summary>
157-
/// <param name="startIndex">The start indexes to be used.</param>
158-
/// <returns>The sliced tensor.</returns>
159-
TSelf Slice(params scoped ReadOnlySpan<NIndex> startIndex);
160-
161-
/// <summary>
162-
/// Slices the tensor using the specified ranges.
163-
/// </summary>
164-
/// <param name="range">The ranges to be used.</param>
165-
/// <returns>The sliced tensor.</returns>
166-
TSelf Slice(params scoped ReadOnlySpan<NRange> range);
167-
168-
/// <summary>
169-
/// Tries to copy the tensor to the specified destination. The destination tensor must be equal to or larger than the source tensor.
170-
/// </summary>
171-
/// <param name="destination">The destination span where the data should be copied to.</param>
172-
/// <returns><see langword="true" /> if the copy succeeded, <see langword="false" /> otherwise.</returns>
173-
bool TryCopyTo(scoped TensorSpan<T> destination);
174-
175-
/// <summary>
176-
/// Tries to flatten the tensor to the specified destination. The destination span must be equal to or larger than the number of elements in the source tensor.
177-
/// </summary>
178-
/// <param name="destination">The destination span where the data should be flattened to.</param>
179-
/// <returns><see langword="true" /> if the flatten succeeded, <see langword="false" /> otherwise.</returns>
180-
bool TryFlattenTo(scoped Span<T> destination);
181-
}
18251
}

0 commit comments

Comments
 (0)