Skip to content

Commit f0f1457

Browse files
Added in non-generic interfaces for Tensors (#113401)
* base tensor updated, need to update ref * ref files updated * added tests * fixed return comment
1 parent 5ec0661 commit f0f1457

File tree

5 files changed

+216
-54
lines changed

5 files changed

+216
-54
lines changed

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

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,28 @@ namespace System.Buffers
5555
}
5656
namespace System.Numerics.Tensors
5757
{
58-
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
59-
public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable where TSelf : System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>
58+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
59+
public partial interface IReadOnlyTensor
6060
{
61-
static abstract TSelf? Empty { get; }
6261
nint FlattenedLength { get; }
6362
bool IsEmpty { get; }
6463
bool IsPinned { get; }
65-
T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; }
66-
TSelf this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get; }
67-
T this[params scoped System.ReadOnlySpan<nint> indexes] { get; }
64+
object this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; }
65+
object this[params scoped System.ReadOnlySpan<nint> indexes] { get; }
6866
[System.Diagnostics.CodeAnalysis.UnscopedRefAttribute]
6967
System.ReadOnlySpan<nint> Lengths { get; }
7068
int Rank { get; }
7169
[System.Diagnostics.CodeAnalysis.UnscopedRefAttribute]
7270
System.ReadOnlySpan<nint> Strides { get; }
71+
System.Buffers.MemoryHandle GetPinnedHandle();
72+
}
73+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
74+
public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor where TSelf : System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>
75+
{
76+
static abstract TSelf? Empty { get; }
77+
new T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; }
78+
TSelf this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get; }
79+
new T this[params scoped System.ReadOnlySpan<nint> indexes] { get; }
7380
System.Numerics.Tensors.ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan();
7481
System.Numerics.Tensors.ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NIndex> startIndex);
7582
System.Numerics.Tensors.ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NRange> range);
@@ -83,18 +90,25 @@ public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.
8390
bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan<T> destination);
8491
bool TryFlattenTo(scoped System.Span<T> destination);
8592
}
86-
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
87-
public partial interface ITensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor<TSelf, T> where TSelf : System.Numerics.Tensors.ITensor<TSelf, T>
93+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
94+
public partial interface ITensor : System.Numerics.Tensors.IReadOnlyTensor
8895
{
8996
bool IsReadOnly { get; }
97+
new object this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; set; }
98+
new object this[params scoped System.ReadOnlySpan<nint> indexes] { get; set; }
99+
void Clear();
100+
void Fill(object value);
101+
}
102+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
103+
public partial interface ITensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>, System.Numerics.Tensors.ITensor where TSelf : System.Numerics.Tensors.ITensor<TSelf, T>
104+
{
90105
new T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; set; }
91106
new TSelf this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get; set; }
92107
new T this[params scoped System.ReadOnlySpan<nint> indexes] { get; set; }
93108
System.Numerics.Tensors.TensorSpan<T> AsTensorSpan();
94109
System.Numerics.Tensors.TensorSpan<T> AsTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NIndex> startIndex);
95110
System.Numerics.Tensors.TensorSpan<T> AsTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NRange> range);
96111
System.Numerics.Tensors.TensorSpan<T> AsTensorSpan(params scoped System.ReadOnlySpan<nint> start);
97-
void Clear();
98112
static abstract TSelf Create(scoped System.ReadOnlySpan<nint> lengths, bool pinned = false);
99113
static abstract TSelf Create(scoped System.ReadOnlySpan<nint> lengths, scoped System.ReadOnlySpan<nint> strides, bool pinned = false);
100114
static abstract TSelf CreateUninitialized(scoped System.ReadOnlySpan<nint> lengths, bool pinned = false);
@@ -816,8 +830,8 @@ public ref partial struct Enumerator
816830
public bool MoveNext() { throw null; }
817831
}
818832
}
819-
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
820-
public sealed partial class Tensor<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>
833+
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
834+
public sealed partial class Tensor<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>, System.Numerics.Tensors.ITensor, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>
821835
{
822836
internal Tensor() { }
823837
public static System.Numerics.Tensors.Tensor<T> Empty { get { throw null; } }
@@ -831,12 +845,16 @@ internal Tensor() { }
831845
public System.ReadOnlySpan<nint> Lengths { get { throw null; } }
832846
public int Rank { get { throw null; } }
833847
public System.ReadOnlySpan<nint> Strides { get { throw null; } }
848+
object System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
849+
object System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
850+
System.ReadOnlySpan<nint> System.Numerics.Tensors.IReadOnlyTensor.Lengths { get { throw null; } }
851+
System.ReadOnlySpan<nint> System.Numerics.Tensors.IReadOnlyTensor.Strides { get { throw null; } }
834852
T System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
835853
System.Numerics.Tensors.Tensor<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>.this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get { throw null; } }
836854
T System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
837-
System.ReadOnlySpan<nint> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>.Lengths { get { throw null; } }
838-
System.ReadOnlySpan<nint> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>.Strides { get { throw null; } }
839-
bool System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>.IsReadOnly { get { throw null; } }
855+
bool System.Numerics.Tensors.ITensor.IsReadOnly { get { throw null; } }
856+
object System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } set { } }
857+
object System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } set { } }
840858
T System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } set { } }
841859
T System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } set { } }
842860
public System.Numerics.Tensors.ReadOnlyTensorSpan<T> AsReadOnlyTensorSpan() { throw null; }
@@ -849,12 +867,14 @@ internal Tensor() { }
849867
public System.Numerics.Tensors.TensorSpan<T> AsTensorSpan(params scoped System.ReadOnlySpan<nint> start) { throw null; }
850868
public void Clear() { }
851869
public void CopyTo(scoped System.Numerics.Tensors.TensorSpan<T> destination) { }
870+
public void Fill(object value) { }
852871
public void Fill(T value) { }
853872
public void FlattenTo(scoped System.Span<T> destination) { }
854873
public System.Collections.Generic.IEnumerator<T> GetEnumerator() { throw null; }
855874
public override int GetHashCode() { throw null; }
856875
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
857876
public ref T GetPinnableReference() { throw null; }
877+
public System.Buffers.MemoryHandle GetPinnedHandle() { throw null; }
858878
public static implicit operator System.Numerics.Tensors.ReadOnlyTensorSpan<T> (System.Numerics.Tensors.Tensor<T> value) { throw null; }
859879
public static implicit operator System.Numerics.Tensors.TensorSpan<T> (System.Numerics.Tensors.Tensor<T> value) { throw null; }
860880
public static implicit operator System.Numerics.Tensors.Tensor<T> (T[] array) { throw null; }

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

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,13 @@
77

88
namespace System.Numerics.Tensors
99
{
10+
1011
/// <summary>
1112
/// Represents a read-only tensor.
1213
/// </summary>
13-
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
14-
/// <typeparam name="T">The element type.</typeparam>
1514
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
16-
public interface IReadOnlyTensor<TSelf, T> : IEnumerable<T>
17-
where TSelf : IReadOnlyTensor<TSelf, T>
15+
public interface IReadOnlyTensor
1816
{
19-
/// <summary>
20-
/// Gets an empty tensor.
21-
/// </summary>
22-
static abstract TSelf? Empty { get; }
23-
2417
/// <summary>
2518
/// Gets a value that indicates whether the collection is currently empty.
2619
/// </summary>
@@ -41,17 +34,62 @@ public interface IReadOnlyTensor<TSelf, T> : IEnumerable<T>
4134
/// </summary>
4235
int Rank { get; }
4336

37+
/// <summary>
38+
/// Gets the length of each dimension in the tensor.
39+
/// </summary>
40+
[UnscopedRef]
41+
ReadOnlySpan<nint> Lengths { get; }
42+
43+
/// <summary>
44+
/// Gets the stride of each dimension in the tensor.
45+
/// </summary>
46+
[UnscopedRef]
47+
ReadOnlySpan<nint> Strides { get; }
48+
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>
64+
/// <returns><see cref="MemoryHandle"/></returns>
65+
MemoryHandle GetPinnedHandle();
66+
}
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+
4482
/// <summary>
4583
/// Gets the value at the specified indexes.
4684
/// </summary>
4785
/// <param name="indexes">The indexes to be used.</param>
48-
T this[params scoped ReadOnlySpan<nint> indexes] { get; }
86+
new T this[params scoped ReadOnlySpan<nint> indexes] { get; }
4987

5088
/// <summary>
5189
/// Gets the value at the specified indexes.
5290
/// </summary>
5391
/// <param name="indexes">The indexes to be used.</param>
54-
T this[params scoped ReadOnlySpan<NIndex> indexes] { get; }
92+
new T this[params scoped ReadOnlySpan<NIndex> indexes] { get; }
5593

5694
/// <summary>
5795
/// Gets the values at the specified ranges.
@@ -98,18 +136,6 @@ public interface IReadOnlyTensor<TSelf, T> : IEnumerable<T>
98136
/// <param name="destination">The destination span where the data should be flattened to.</param>
99137
void FlattenTo(scoped Span<T> destination);
100138

101-
/// <summary>
102-
/// Gets the length of each dimension in the tensor.
103-
/// </summary>
104-
[UnscopedRef]
105-
ReadOnlySpan<nint> Lengths { get; }
106-
107-
/// <summary>
108-
/// Gets the stride of each dimension in the tensor.
109-
/// </summary>
110-
[UnscopedRef]
111-
ReadOnlySpan<nint> Strides { get; }
112-
113139
/// <summary>
114140
/// Returns a reference to the 0th element of the tensor. If the tensor is empty, returns <see langword="null"/>.
115141
/// </summary>

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

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,47 @@
66

77
namespace System.Numerics.Tensors
88
{
9+
/// <summary>
10+
/// Represents a tensor.
11+
/// </summary>
12+
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
13+
public interface ITensor : IReadOnlyTensor
14+
{
15+
/// <summary>
16+
/// Gets the value at the specified indexes.
17+
/// </summary>
18+
/// <param name="indexes">The indexes to be used.</param>
19+
new object this[params scoped ReadOnlySpan<nint> indexes] { get; set; }
20+
21+
/// <summary>
22+
/// Gets the value at the specified indexes.
23+
/// </summary>
24+
/// <param name="indexes">The indexes to be used.</param>
25+
new object this[params scoped ReadOnlySpan<NIndex> indexes] { get; set; }
26+
27+
/// <summary>
28+
/// Gets a value that indicates whether the collection is read-only.
29+
/// </summary>
30+
bool IsReadOnly { get; }
31+
32+
/// <summary>
33+
/// Clears the tensor.
34+
/// </summary>
35+
void Clear();
36+
37+
/// <summary>
38+
/// Fills the contents of this tensor with the given value.
39+
/// </summary>
40+
void Fill(object value);
41+
}
42+
943
/// <summary>
1044
/// Represents a tensor.
1145
/// </summary>
1246
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
1347
/// <typeparam name="T">The element type.</typeparam>
1448
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
15-
public interface ITensor<TSelf, T>
16-
: IReadOnlyTensor<TSelf, T>
49+
public interface ITensor<TSelf, T> : ITensor, IReadOnlyTensor<TSelf, T>
1750
where TSelf : ITensor<TSelf, T>
1851
{
1952
// TODO: Determine if we can implement `IEqualityOperators<TSelf, T, bool>`.
@@ -67,11 +100,6 @@ public interface ITensor<TSelf, T>
67100
/// </remarks>
68101
static abstract TSelf CreateUninitialized(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false);
69102

70-
/// <summary>
71-
/// Gets a value that idicates whether the collection is read-only.
72-
/// </summary>
73-
bool IsReadOnly { get; }
74-
75103
/// <summary>
76104
/// Gets the value at the specified indexes.
77105
/// </summary>
@@ -117,11 +145,6 @@ public interface ITensor<TSelf, T>
117145
/// <returns>The converted <see cref="TensorSpan{T}"/>.</returns>
118146
TensorSpan<T> AsTensorSpan(params scoped ReadOnlySpan<NRange> range);
119147

120-
/// <summary>
121-
/// Clears the tensor.
122-
/// </summary>
123-
void Clear();
124-
125148
/// <summary>
126149
/// Fills the contents of this tensor with the given value.
127150
/// </summary>

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

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ namespace System.Numerics.Tensors
2121
/// Represents a tensor.
2222
/// </summary>
2323
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
24-
public sealed class Tensor<T>
25-
: ITensor<Tensor<T>, T>
24+
public sealed class Tensor<T> : ITensor, ITensor<Tensor<T>, T>
2625
{
2726
/// <summary>A byref or a native ptr.</summary>
2827
internal readonly T[] _values;
@@ -176,7 +175,7 @@ static Tensor<T> ITensor<Tensor<T>, T>.CreateUninitialized(scoped ReadOnlySpan<n
176175
/// Gets the length of each dimension in this <see cref="Tensor{T}"/>.
177176
/// </summary>
178177
/// <value><see cref="ReadOnlySpan{T}"/> with the lengths of each dimension.</value>
179-
ReadOnlySpan<nint> IReadOnlyTensor<Tensor<T>, T>.Lengths => _lengths;
178+
ReadOnlySpan<nint> IReadOnlyTensor.Lengths => _lengths;
180179

181180

182181
/// <summary>
@@ -189,9 +188,16 @@ static Tensor<T> ITensor<Tensor<T>, T>.CreateUninitialized(scoped ReadOnlySpan<n
189188
/// Gets the strides of each dimension in this <see cref="Tensor{T}"/>.
190189
/// </summary>
191190
/// <value><see cref="ReadOnlySpan{T}"/> with the strides of each dimension.</value>
192-
ReadOnlySpan<nint> IReadOnlyTensor<Tensor<T>, T>.Strides => _strides;
191+
ReadOnlySpan<nint> IReadOnlyTensor.Strides => _strides;
193192

194-
bool ITensor<Tensor<T>, T>.IsReadOnly => false;
193+
bool ITensor.IsReadOnly => false;
194+
195+
object IReadOnlyTensor.this[params scoped ReadOnlySpan<NIndex> indexes] => this[indexes]!;
196+
197+
object IReadOnlyTensor.this[params scoped ReadOnlySpan<nint> indexes] => this[indexes]!;
198+
199+
object ITensor.this[params scoped ReadOnlySpan<NIndex> indexes] { get => this[indexes]!; set => this[indexes] = (T)value; }
200+
object ITensor.this[params scoped ReadOnlySpan<nint> indexes] { get => this[indexes]!; set => this[indexes] = (T)value; }
195201

196202
/// <summary>
197203
/// Returns a reference to specified element of the Tensor.
@@ -524,6 +530,11 @@ public Tensor<T> Slice(params ReadOnlySpan<NIndex> startIndex)
524530
[MethodImpl(MethodImplOptions.AggressiveInlining)]
525531
public void Fill(T value) => AsTensorSpan().Fill(value);
526532

533+
/// <summary>
534+
/// Fills the contents of this span with the given value.
535+
/// </summary>
536+
public void Fill(object value) => Fill(value is T t ? t : throw new ArgumentException($"Cannot convert {value} to {typeof(T)}"));
537+
527538
/// <summary>
528539
/// Copies the contents of this tensor into destination span. If the source
529540
/// and destinations overlap, this method behaves as if the original values in
@@ -671,5 +682,18 @@ public string ToString(params ReadOnlySpan<nint> maximumLengths)
671682
sb.AppendLine("}");
672683
return sb.ToString();
673684
}
685+
686+
/// <summary>
687+
/// Pins and gets a <see cref="MemoryHandle"/> to the backing memory.
688+
/// </summary>
689+
/// <returns>A <see cref="MemoryHandle"/> which has pinned the backing memory.</returns>
690+
public MemoryHandle GetPinnedHandle()
691+
{
692+
GCHandle handle = GCHandle.Alloc(_values, GCHandleType.Pinned);
693+
unsafe
694+
{
695+
return new MemoryHandle(Unsafe.AsPointer(ref GetPinnableReference()), handle);
696+
}
697+
}
674698
}
675699
}

0 commit comments

Comments
 (0)