Skip to content

Commit 88013cb

Browse files
Fixing API to use in and ReadOnly as needed (#103368)
* fixing API to use in and ReadOnly as needed * test fixes * API updates from Tanner's suggestion * test fixes * removed InPlace, changes from PR discussions
1 parent 33e550a commit 88013cb

12 files changed

+2925
-4527
lines changed

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

Lines changed: 231 additions & 362 deletions
Large diffs are not rendered by default.

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,7 @@
225225
<data name="Argument_IncompatibleDimensions" xml:space="preserve">
226226
<value>Incompatible dimensions for provided tensors. left.Lengths[1] == {0} while right.Lengths[1] == {1}.</value>
227227
</data>
228-
</root>
228+
<data name="ThrowArgument_StackShapesNotSame" xml:space="preserve">
229+
<value>All tensors must have the same shape.</value>
230+
</data>
231+
</root>

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
<Compile Include="System\Numerics\Tensors\netcore\ITensor.cs" />
2424
<Compile Include="System\Numerics\Tensors\netcore\IReadOnlyTensor.cs" />
2525
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanDebugView.cs" />
26-
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanExtensions.cs" />
2726
<Compile Include="System\Numerics\Tensors\netcore\ReadOnlyTensorSpan.cs" />
2827
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.cs" />
2928
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.T.cs" />

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,14 @@ public void FlattenTo(scoped Span<T> destination)
775775
nint copiedValues = 0;
776776
while (copiedValues < _flattenedLength)
777777
{
778-
TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]);
778+
if (Strides[Rank - 1] == 0)
779+
{
780+
destination.Slice(checked((int)copiedValues), (int)Lengths[Rank - 1]).Fill(Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)));
781+
}
782+
else
783+
{
784+
TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]);
785+
}
779786
TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths);
780787
copiedValues += Lengths[Rank - 1];
781788
}

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

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.Linq;
6+
using System.Runtime.InteropServices;
67
using Microsoft.VisualBasic;
78

89
#pragma warning disable CS8601 // Possible null reference assignment.
@@ -19,7 +20,6 @@ public static partial class Tensor
1920
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
2021
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
2122
public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
22-
where T : IEquatable<T>
2323
{
2424
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
2525
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
@@ -33,7 +33,6 @@ public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, bool pinned
3333
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
3434
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
3535
public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false)
36-
where T : IEquatable<T>
3736
{
3837
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
3938
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
@@ -48,7 +47,7 @@ public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, scoped Read
4847
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
4948
/// <exception cref="ArgumentOutOfRangeException"></exception>
5049
public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths)
51-
where T : IEquatable<T> => Create(values, lengths, []);
50+
=> Create(values, lengths, []);
5251

5352
/// <summary>
5453
/// Creates a <see cref="Tensor{T}"/> from the provided <paramref name="values"/>. If the product of the
@@ -60,51 +59,40 @@ public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths)
6059
/// <param name="isPinned">A <see cref="bool"/> indicating whether the <paramref name="values"/> were pinned or not.</param>
6160
/// <exception cref="ArgumentOutOfRangeException"></exception>
6261
public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool isPinned = false)
63-
where T : IEquatable<T>
6462
{
6563
return new Tensor<T>(values, lengths, strides, isPinned);
6664
}
6765

6866
/// <summary>
69-
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
70-
/// </summary>
71-
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
72-
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
73-
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
74-
where T : IEquatable<T> => CreateUninitialized<T>(lengths, [], pinned);
75-
76-
77-
/// <summary>
78-
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
67+
/// Creates a <see cref="Tensor{T}"/> and initializes it with the data from <paramref name="data"/>.
7968
/// </summary>
80-
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
81-
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
82-
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
83-
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false )
84-
where T : IEquatable<T>
69+
/// <param name="data">A <see cref="IEnumerable{T}"/> with the data to use for the initialization.</param>
70+
/// <param name="lengths"></param>
71+
public static Tensor<T> Create<T>(IEnumerable<T> data, scoped ReadOnlySpan<nint> lengths)
8572
{
86-
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
87-
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
88-
return new Tensor<T>(values, lengths, strides, pinned);
73+
T[] values = data.ToArray();
74+
return new Tensor<T>(values, lengths.IsEmpty ? [values.Length] : lengths, false);
8975
}
9076

9177
/// <summary>
9278
/// Creates a <see cref="Tensor{T}"/> and initializes it with the data from <paramref name="data"/>.
9379
/// </summary>
9480
/// <param name="data">A <see cref="IEnumerable{T}"/> with the data to use for the initialization.</param>
95-
public static Tensor<T> CreateFromEnumerable<T>(IEnumerable<T> data)
96-
where T : IEquatable<T>, IEqualityOperators<T, T, bool>
81+
/// <param name="lengths"></param>
82+
/// <param name="strides"></param>
83+
/// <param name="isPinned"></param>
84+
public static Tensor<T> Create<T>(IEnumerable<T> data, scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool isPinned = false)
9785
{
9886
T[] values = data.ToArray();
99-
return new Tensor<T>(values, [values.Length], false);
87+
return new Tensor<T>(values, lengths.IsEmpty ? [values.Length] : lengths, strides, isPinned);
10088
}
10189

10290
/// <summary>
10391
/// Creates a <see cref="Tensor{T}"/> and initializes it with random data uniformly distributed.
10492
/// </summary>
10593
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
10694
public static Tensor<T> CreateAndFillUniformDistribution<T>(params scoped ReadOnlySpan<nint> lengths)
107-
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
95+
where T : IFloatingPoint<T>
10896
{
10997
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
11098
T[] values = new T[linearLength];
@@ -121,16 +109,16 @@ public static Tensor<T> CreateAndFillUniformDistribution<T>(params scoped ReadOn
121109
/// </summary>
122110
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
123111
public static Tensor<T> CreateAndFillGaussianNormalDistribution<T>(params scoped ReadOnlySpan<nint> lengths)
124-
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
112+
where T : IFloatingPoint<T>
125113
{
126114
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
127115
T[] values = new T[linearLength];
128-
GaussianDistribution(ref values, linearLength);
116+
GaussianDistribution<T>(values, linearLength);
129117
return new Tensor<T>(values, lengths, false);
130118
}
131119

132-
private static void GaussianDistribution<T>(ref T[] values, nint linearLength)
133-
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
120+
private static void GaussianDistribution<T>(in Span<T> values, nint linearLength)
121+
where T : IFloatingPoint<T>
134122
{
135123
Random rand = Random.Shared;
136124
for (int i = 0; i < linearLength; i++)
@@ -141,5 +129,45 @@ private static void GaussianDistribution<T>(ref T[] values, nint linearLength)
141129
}
142130
}
143131
#endregion
132+
133+
/// <summary>
134+
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
135+
/// </summary>
136+
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
137+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
138+
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
139+
=> CreateUninitialized<T>(lengths, [], pinned);
140+
141+
/// <summary>
142+
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
143+
/// </summary>
144+
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
145+
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
146+
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
147+
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false)
148+
{
149+
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
150+
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
151+
return new Tensor<T>(values, lengths, strides, pinned);
152+
}
153+
154+
public static ref readonly TensorSpan<T> FillGaussianNormalDistribution<T>(in TensorSpan<T> destination) where T : IFloatingPoint<T>
155+
{
156+
Span<T> span = MemoryMarshal.CreateSpan<T>(ref destination._reference, (int)destination._flattenedLength);
157+
158+
GaussianDistribution<T>(span, destination._flattenedLength);
159+
160+
return ref destination;
161+
}
162+
163+
public static ref readonly TensorSpan<T> FillUniformDistribution<T>(in TensorSpan<T> destination) where T : IFloatingPoint<T>
164+
{
165+
Span<T> span = MemoryMarshal.CreateSpan<T>(ref destination._reference, (int)destination._flattenedLength);
166+
167+
for (int i = 0; i < span.Length; i++)
168+
span[i] = T.CreateChecked(Random.Shared.NextDouble());
169+
170+
return ref destination;
171+
}
144172
}
145173
}

0 commit comments

Comments
 (0)