diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs index f18aa5cb1d69e8..be128658eddaee 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs @@ -1932,16 +1932,26 @@ public static Tensor SqueezeDimension(this Tensor tensor, int dimension if (dimension == -1) { + int removalCount = tensor.Lengths.Count(1); + int removedIndex = 0; + Span removed = TensorOperation.RentedBuffer.CreateUninitialized(removalCount, out TensorOperation.RentedBuffer removedRentedBuffer); + for (int i = 0; i < tensor.Lengths.Length; i++) { if (tensor.Lengths[i] != 1) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed[removedIndex++] = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); + removedRentedBuffer.Dispose(); } else { @@ -1949,19 +1959,25 @@ public static Tensor SqueezeDimension(this Tensor tensor, int dimension { ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); } + int removed = default; for (int i = 0; i < tensor.Lengths.Length; i++) { if (i != dimension) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); } - Tensor output = new Tensor(tensor._values, tensor._start, lengths, strides, strideOrder); + Tensor output = new Tensor(tensor._values, tensor._start, lengths[..newRank], strides[..newRank], strideOrder[..newRank]); lengthsRentedBuffer.Dispose(); stridesRentedBuffer.Dispose(); @@ -1998,16 +2014,26 @@ public static TensorSpan SqueezeDimension(in this TensorSpan tensor, in if (dimension == -1) { + int removalCount = tensor.Lengths.Count(1); + int removedIndex = 0; + Span removed = TensorOperation.RentedBuffer.CreateUninitialized(removalCount, out TensorOperation.RentedBuffer removedRentedBuffer); + for (int i = 0; i < tensor.Lengths.Length; i++) { if (tensor.Lengths[i] != 1) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed[removedIndex++] = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); + removedRentedBuffer.Dispose(); } else { @@ -2015,19 +2041,25 @@ public static TensorSpan SqueezeDimension(in this TensorSpan tensor, in { ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); } + int removed = default; for (int i = 0; i < tensor.Lengths.Length; i++) { if (i != dimension) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); } - TensorSpan output = new TensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths, strides, strideOrder); + TensorSpan output = new TensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths[..newRank], strides[..newRank], strideOrder[..newRank]); lengthsRentedBuffer.Dispose(); stridesRentedBuffer.Dispose(); @@ -2064,16 +2096,26 @@ public static ReadOnlyTensorSpan SqueezeDimension(in this ReadOnlyTensorSp if (dimension == -1) { + int removalCount = tensor.Lengths.Count(1); + int removedIndex = 0; + Span removed = TensorOperation.RentedBuffer.CreateUninitialized(removalCount, out TensorOperation.RentedBuffer removedRentedBuffer); + for (int i = 0; i < tensor.Lengths.Length; i++) { if (tensor.Lengths[i] != 1) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed[removedIndex++] = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); + removedRentedBuffer.Dispose(); } else { @@ -2081,19 +2123,25 @@ public static ReadOnlyTensorSpan SqueezeDimension(in this ReadOnlyTensorSp { ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); } + int removed = default; for (int i = 0; i < tensor.Lengths.Length; i++) { if (i != dimension) { lengths[index] = tensor.Lengths[i]; strides[index] = tensor.Strides[i]; - strideOrder[index++] = tensor._shape.LinearRankOrder[i]; newRank++; + strideOrder[index++] = tensor._shape.LinearRankOrder[i]; + } + else + { + removed = tensor._shape.LinearRankOrder[i]; } } + SqueezeHelper(removed, strideOrder); } - ReadOnlyTensorSpan output = new ReadOnlyTensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths, strides, strideOrder); + ReadOnlyTensorSpan output = new ReadOnlyTensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths[..newRank], strides[..newRank], strideOrder[..newRank]); lengthsRentedBuffer.Dispose(); stridesRentedBuffer.Dispose(); @@ -2101,6 +2149,31 @@ public static ReadOnlyTensorSpan SqueezeDimension(in this ReadOnlyTensorSp return output; } + + internal static void SqueezeHelper(scoped in Span removed, scoped in Span strideOrder) + { + for (int i = 0; i < strideOrder.Length; i++) + { + for (int j = removed.Length - 1; j >= 0; j--) + { + if (strideOrder[i] > removed[j]) + { + strideOrder[i]--; + } + } + } + } + + internal static void SqueezeHelper(int removed, scoped in Span strideOrder) + { + for (int i = 0; i < strideOrder.Length; i++) + { + if (strideOrder[i] > removed) + { + strideOrder[i]--; + } + } + } #endregion #region Stack @@ -2367,29 +2440,28 @@ public static Tensor Unsqueeze(this Tensor tensor, int dimension) if (dimension < 0) dimension = tensor.Rank - dimension; - scoped Span lengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank, out TensorOperation.RentedBuffer xRentedBuffer); + scoped Span newLengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer lengthsRentedBuffer); - tensor.Lengths.Slice(0, dimension).CopyTo(lengths); - tensor.Lengths.Slice(dimension).CopyTo(lengths.Slice(dimension + 1)); - lengths[dimension] = 1; + tensor.Lengths.Slice(0, dimension).CopyTo(newLengths); + tensor.Lengths.Slice(dimension).CopyTo(newLengths.Slice(dimension + 1)); + newLengths[dimension] = 1; - Span strides = tensor.Strides.Length + 1 <= TensorShape.MaxInlineRank ? - stackalloc nint[tensor.Strides.Length + 1] : - new nint[tensor.Strides.Length + 1]; + Span newStrides = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer stridesRentedBuffer); if (dimension == tensor.Rank) { - tensor.Strides.CopyTo(strides); - strides[dimension] = tensor.Strides[dimension - 1]; + tensor.Strides.CopyTo(newStrides); + newStrides[dimension] = 0; } else { - tensor.Strides.Slice(0, dimension).CopyTo(strides); - tensor.Strides.Slice(dimension).CopyTo(strides.Slice(dimension + 1)); - strides[dimension] = tensor.Strides[dimension] * tensor.Lengths[dimension]; + tensor.Strides.Slice(0, dimension).CopyTo(newStrides); + tensor.Strides.Slice(dimension).CopyTo(newStrides.Slice(dimension + 1)); + newStrides[dimension] = 0; } - Tensor output = new Tensor(tensor._values, tensor._start, lengths, strides); - xRentedBuffer.Dispose(); + Tensor output = new Tensor(tensor._values, tensor._start, newLengths, newStrides); + lengthsRentedBuffer.Dispose(); + stridesRentedBuffer.Dispose(); return output; } @@ -2405,29 +2477,28 @@ public static TensorSpan Unsqueeze(in this TensorSpan tensor, int dimen if (dimension < 0) dimension = tensor.Rank - dimension; - scoped Span lengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank, out TensorOperation.RentedBuffer xRentedBuffer); + scoped Span newLengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer lengthsRentedBuffer); - tensor.Lengths.Slice(0, dimension).CopyTo(lengths); - tensor.Lengths.Slice(dimension).CopyTo(lengths.Slice(dimension + 1)); - lengths[dimension] = 1; + tensor.Lengths.Slice(0, dimension).CopyTo(newLengths); + tensor.Lengths.Slice(dimension).CopyTo(newLengths.Slice(dimension + 1)); + newLengths[dimension] = 1; - Span strides = tensor.Strides.Length + 1 <= TensorShape.MaxInlineRank ? - stackalloc nint[tensor.Strides.Length + 1] : - new nint[tensor.Strides.Length + 1]; + Span newStrides = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer stridesRentedBuffer); if (dimension == tensor.Rank) { - tensor.Strides.CopyTo(strides); - strides[dimension] = tensor.Strides[dimension - 1]; + tensor.Strides.CopyTo(newStrides); + newStrides[dimension] = 0; } else { - tensor.Strides.Slice(0, dimension).CopyTo(strides); - tensor.Strides.Slice(dimension).CopyTo(strides.Slice(dimension + 1)); - strides[dimension] = tensor.Strides[dimension] * tensor.Lengths[dimension]; + tensor.Strides.Slice(0, dimension).CopyTo(newStrides); + tensor.Strides.Slice(dimension).CopyTo(newStrides.Slice(dimension + 1)); + newStrides[dimension] = 0; } - TensorSpan output = new TensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths, strides); - xRentedBuffer.Dispose(); + TensorSpan output = new TensorSpan(ref tensor._reference, tensor._shape.LinearLength, newLengths, newStrides); + lengthsRentedBuffer.Dispose(); + stridesRentedBuffer.Dispose(); return output; } @@ -2443,29 +2514,28 @@ public static ReadOnlyTensorSpan Unsqueeze(in this ReadOnlyTensorSpan t if (dimension < 0) dimension = tensor.Rank - dimension; - scoped Span lengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank, out TensorOperation.RentedBuffer xRentedBuffer); + scoped Span newLengths = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer lengthsRentedBuffer); - tensor.Lengths.Slice(0, dimension).CopyTo(lengths); - tensor.Lengths.Slice(dimension).CopyTo(lengths.Slice(dimension + 1)); - lengths[dimension] = 1; + tensor.Lengths.Slice(0, dimension).CopyTo(newLengths); + tensor.Lengths.Slice(dimension).CopyTo(newLengths.Slice(dimension + 1)); + newLengths[dimension] = 1; - Span strides = tensor.Strides.Length + 1 <= TensorShape.MaxInlineRank ? - stackalloc nint[tensor.Strides.Length + 1] : - new nint[tensor.Strides.Length + 1]; + Span newStrides = TensorOperation.RentedBuffer.CreateUninitialized(tensor.Rank + 1, out TensorOperation.RentedBuffer stridesRentedBuffer); if (dimension == tensor.Rank) { - tensor.Strides.CopyTo(strides); - strides[dimension] = tensor.Strides[dimension - 1]; + tensor.Strides.CopyTo(newStrides); + newStrides[dimension] = 0; } else { - tensor.Strides.Slice(0, dimension).CopyTo(strides); - tensor.Strides.Slice(dimension).CopyTo(strides.Slice(dimension + 1)); - strides[dimension] = tensor.Strides[dimension] * tensor.Lengths[dimension]; + tensor.Strides.Slice(0, dimension).CopyTo(newStrides); + tensor.Strides.Slice(dimension).CopyTo(newStrides.Slice(dimension + 1)); + newStrides[dimension] = 0; } - ReadOnlyTensorSpan output = new ReadOnlyTensorSpan(ref tensor._reference, tensor._shape.LinearLength, lengths, strides); - xRentedBuffer.Dispose(); + ReadOnlyTensorSpan output = new ReadOnlyTensorSpan(ref tensor._reference, tensor._shape.LinearLength, newLengths, newStrides); + lengthsRentedBuffer.Dispose(); + stridesRentedBuffer.Dispose(); return output; } #endregion diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorOperation.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorOperation.cs index 7c5d1833fe7278..cb7d42159f231e 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorOperation.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorOperation.cs @@ -35,7 +35,7 @@ public static bool Invoke(in ReadOnlyTensorSpan x, in Re scoped Span xIndexes = RentedBuffer.Create(destinationShape.Rank, x.Strides, out nint xLinearOffset, out RentedBuffer xRentedBuffer); scoped Span yIndexes = RentedBuffer.Create(destinationShape.Rank, y.Strides, out nint yLinearOffset, out RentedBuffer yRentedBuffer); - for (nint i = 0; i < x.FlattenedLength; i++) + for (nint i = 0; i < destinationShape.FlattenedLength; i++) { xLinearOffset = x._shape.AdjustToNextIndex(destinationShape, xLinearOffset, xIndexes); yLinearOffset = y._shape.AdjustToNextIndex(destinationShape, yLinearOffset, yIndexes); @@ -1972,7 +1972,7 @@ public struct SumOfSquaredDifferences { public static void Invoke(ref readonly T x, T y, ref T destination) { - destination = (x - y) * (x - y); + destination += (x - y) * (x - y); } public static void Invoke(ReadOnlySpan x, T y, Span destination) { @@ -1984,7 +1984,7 @@ public static void Invoke(ReadOnlySpan x, T y, Span destination) public static void Invoke(ref readonly T x, ref readonly T y, ref T destination) { - destination = (x - y) * (x - y); + destination += (x - y) * (x - y); } public static void Invoke(ReadOnlySpan x, ReadOnlySpan y, Span destination) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs index 1033e46d8c513a..2a21b93a2c9cc5 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs @@ -71,7 +71,7 @@ private TensorShape(nint linearLength, scoped ReadOnlySpan lengths, scoped if (rank == 0) { - lengths = [linearLength]; + lengths = [0]; rank = 1; } Debug.Assert(rank >= 1); @@ -281,7 +281,7 @@ ref Unsafe.As(ref metadata[rank * 2]), private TensorShape(nint flattenedLength, nint linearLength, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, scoped ReadOnlySpan linearRankOrder, int rank) { - Debug.Assert((linearLength == 0) || ((flattenedLength % linearLength) == 0)); + Debug.Assert((linearLength == 0) || (linearLength >= flattenedLength)); Debug.Assert(lengths.Length == rank); Debug.Assert(strides.Length == rank); @@ -451,11 +451,12 @@ public nint AdjustToNextIndex(in TensorShape destinationShape, nint linearOffset for (int i = 0; i < strides.Length; i++) { int rankIndex = lengths.Length - (i + 1); + int destinationRankIndex = destinationShape.Lengths.Length - (i + 1); nint length = lengths[rankIndex]; nint stride = strides[rankIndex]; - nint index = ++indexes[rankIndex]; + nint index = ++indexes[destinationRankIndex]; linearOffset += stride; if (index < length) @@ -463,7 +464,7 @@ public nint AdjustToNextIndex(in TensorShape destinationShape, nint linearOffset return linearOffset; } - indexes[rankIndex] = 0; + indexes[destinationRankIndex] = 0; linearOffset -= (stride * length); } @@ -481,7 +482,11 @@ public nint AdjustToNextIndex(in TensorShape destinationShape, nint linearOffset if (index < length) { - break; + // If we just break here we end up returning -strides[^1] as the linear offset. + // If strides[^1] is 1, then we return -1 which is not correct and it ends the outer loop early. + // By returning the linear offset here we ensure that the outer loop continues and handles the + // broadcast case correctly. + return linearOffset; } indexes[rankIndex] = 0; @@ -974,8 +979,7 @@ public TensorShape Slice(ReadOnlySpan state, out nint // assume that the previousShape is already valid and the new shape // will strictly be the same size or smaller. - nint flattenedLength = 0; - nint linearLength = 0; + nint flattenedLength = 1; nint computedOffset = 0; for (int i = 0; i < state.Length; i++) @@ -995,7 +999,7 @@ public TensorShape Slice(ReadOnlySpan state, out nint TensorShape result = new TensorShape( flattenedLength, - linearLength, + LinearLength - computedOffset, intermediateLengths, strides, linearRankOrder, diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor_1.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor_1.cs index f0cce74714ae20..6ab7024fed00cd 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor_1.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor_1.cs @@ -125,13 +125,13 @@ private Tensor() /// public ref T this[params scoped ReadOnlySpan indexes] { - get => ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _shape.GetLinearOffset(indexes)); + get => ref Unsafe.Add(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _start), _shape.GetLinearOffset(indexes)); } /// public ref T this[params scoped ReadOnlySpan indexes] { - get => ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _shape.GetLinearOffset(indexes)); + get => ref Unsafe.Add(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_values), _start), _shape.GetLinearOffset(indexes)); } /// diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs index 2eba1f2e912b66..16a2f1fa6af4f7 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -251,11 +251,11 @@ public static void TensorLargeDimensionsTests() Assert.Equal(1, tensor.Lengths[4]); Assert.Equal(6, tensor.Lengths[5]); Assert.Equal(6, tensor.Strides.Length); - Assert.Equal(6, tensor.Strides[0]); - Assert.Equal(6, tensor.Strides[1]); - Assert.Equal(6, tensor.Strides[2]); - Assert.Equal(6, tensor.Strides[3]); - Assert.Equal(6, tensor.Strides[4]); + Assert.Equal(0, tensor.Strides[0]); + Assert.Equal(0, tensor.Strides[1]); + Assert.Equal(0, tensor.Strides[2]); + Assert.Equal(0, tensor.Strides[3]); + Assert.Equal(0, tensor.Strides[4]); Assert.Equal(1, tensor.Strides[5]); Assert.Equal(91, tensor[0, 0, 0, 0, 0, 0]); Assert.Equal(92, tensor[0, 0, 0, 0, 0, 1]); @@ -277,11 +277,11 @@ public static void TensorLargeDimensionsTests() Assert.Equal(1, tensor.Lengths[4]); Assert.Equal(3, tensor.Lengths[5]); Assert.Equal(6, tensor.Strides.Length); - Assert.Equal(12, tensor.Strides[0]); + Assert.Equal(0, tensor.Strides[0]); Assert.Equal(6, tensor.Strides[1]); Assert.Equal(3, tensor.Strides[2]); - Assert.Equal(3, tensor.Strides[3]); - Assert.Equal(3, tensor.Strides[4]); + Assert.Equal(0, tensor.Strides[3]); + Assert.Equal(0, tensor.Strides[4]); Assert.Equal(1, tensor.Strides[5]); Assert.Equal(91, tensor[0, 0, 0, 0, 0, 0]); Assert.Equal(92, tensor[0, 0, 0, 0, 0, 1]); @@ -308,11 +308,11 @@ public static void TensorFactoryCreateUninitializedTests() Assert.Equal(1, t1.Lengths.Length); Assert.Equal(1, t1.Lengths[0]); Assert.Equal(1, t1.Strides.Length); - Assert.Equal(1, t1.Strides[0]); + Assert.Equal(0, t1.Strides[0]); Assert.False(t1.IsPinned); // Make sure can't index too many dimensions - Assert.Throws(() => + Assert.Throws(() => { var x = t1[1, 1]; }); @@ -366,7 +366,7 @@ public static void TensorFactoryCreateUninitializedTests() Assert.Equal(1, t1.Lengths.Length); Assert.Equal(1, t1.Lengths[0]); Assert.Equal(1, t1.Strides.Length); - Assert.Equal(1, t1.Strides[0]); + Assert.Equal(0, t1.Strides[0]); Assert.True(t1.IsPinned); // Make sure 2D array works with basic strides @@ -427,7 +427,7 @@ public static void TensorFactoryCreateUninitializedTests() Assert.Equal(t1[1, 0], t1[1, 1]); // Make sure you can't overlap elements using strides - Assert.Throws(() => { + Assert.Throws(() => { var t1 = Tensor.CreateUninitialized([2, 2], [1, 1], false); }); } @@ -441,12 +441,12 @@ public static void TensorFactoryCreateTests() Assert.Equal(1, t1.Lengths.Length); Assert.Equal(1, t1.Lengths[0]); Assert.Equal(1, t1.Strides.Length); - Assert.Equal(1, t1.Strides[0]); + Assert.Equal(0, t1.Strides[0]); Assert.False(t1.IsPinned); Assert.Equal(0, t1[0]); // Make sure can't index too many dimensions - Assert.Throws(() => + Assert.Throws(() => { var x = t1[1, 1]; }); @@ -487,11 +487,9 @@ public static void TensorFactoryCreateTests() // Null should behave like empty array since there is no "null" span. t1 = Tensor.Create(null); - Assert.Equal(1, t1.Rank); - Assert.Equal(1, t1.Lengths.Length); - Assert.Equal(0, t1.Lengths[0]); - Assert.Equal(1, t1.Strides.Length); - Assert.Equal(0, t1.Strides[0]); + Assert.Equal(0, t1.Rank); + Assert.Equal(0, t1.Lengths.Length); + Assert.Equal(0, t1.Strides.Length); Assert.False(t1.IsPinned); // Make sure pinned works @@ -500,7 +498,7 @@ public static void TensorFactoryCreateTests() Assert.Equal(1, t1.Lengths.Length); Assert.Equal(1, t1.Lengths[0]); Assert.Equal(1, t1.Strides.Length); - Assert.Equal(1, t1.Strides[0]); + Assert.Equal(0, t1.Strides[0]); Assert.True(t1.IsPinned); Assert.Equal(0, t1[0]); @@ -592,14 +590,14 @@ public static void TensorCosineSimilarityTests() Tensor result = Tensor.Create(a, lengths: [2, 1]); - result[0, 0] = Tensor.CosineSimilarity(left.AsReadOnlyTensorSpan([0..1, 0..]), right[0..1, 0..]); - result[1, 0] = Tensor.CosineSimilarity(left.AsReadOnlyTensorSpan([0..1, 0..]), right[0..1, 0..]); + result[0, 0] = Tensor.CosineSimilarity(left.AsReadOnlyTensorSpan([0..1, 0.. ]), right[0..1, 0..]); + result[1, 0] = Tensor.CosineSimilarity(left.AsReadOnlyTensorSpan([1.., 0..]), right[1.., 0..]); Assert.Equal(2, result.Rank); Assert.Equal(2, result.Lengths[0]); Assert.Equal(1, result.Lengths[1]); - Assert.Equal(0.57735, result[0, 0], .00001); + Assert.Equal(float.NaN, result[0, 0]); Assert.Equal(0.81649, result[1, 0], .00001); } @@ -945,7 +943,7 @@ public static void TensorSetSliceTests() { Tensor t0 = Tensor.Create(Enumerable.Range(0, 10), lengths: [2, 5]); Tensor t1 = Tensor.Create(Enumerable.Range(10, 10), lengths: [2, 5]); - Tensor.SetSlice(t0, t1); + Tensor.SetSlice(t0, t1, .., ..); Assert.Equal(10, t0[0, 0]); Assert.Equal(11, t0[0, 1]); @@ -1168,11 +1166,11 @@ public static void TensorSumTests() sum = Tensor.Sum(t1); Assert.Equal(9, sum); - Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: -1, lengths: [2, 3], strides: [])); - Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: 100, lengths: [2, 3], strides: [])); - Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: int.MinValue, lengths: [2, 3], strides: [])); - Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: int.MaxValue, lengths: [2, 3], strides: [])); - Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: 2, lengths: [2, 3], strides: [])); + Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: -1, lengths: [2, 3], strides: [])); + Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: 100, lengths: [2, 3], strides: [])); + Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: int.MinValue, lengths: [2, 3], strides: [])); + Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: int.MaxValue, lengths: [2, 3], strides: [])); + Assert.Throws(()=> Tensor.Create(new float[] { 1, 2, 3, 4, 5, 6 }, start: 2, lengths: [2, 3], strides: [])); } public static float StdDev(float[] values) @@ -1890,7 +1888,7 @@ public static void TensorCopyTest() } ); - Assert.Throws(() => + Assert.Throws(() => { var l = leftData.AsTensorSpan([3, 3, 3]); var r = new TensorSpan(); @@ -2207,7 +2205,7 @@ public static void TensorUnsqueezeTest() Assert.Equal(0, tensor.Strides[0]); Assert.Equal(0, tensor.Strides[1]); - tensor = Tensor.Create([2], false); + tensor = Tensor.Create((ReadOnlySpan)[2], false); Assert.Equal(1, tensor.Rank); Assert.Equal(2, tensor.Lengths[0]); Assert.Equal(1, tensor.Strides[0]); @@ -2216,7 +2214,7 @@ public static void TensorUnsqueezeTest() Assert.Equal(2, tensor.Rank); Assert.Equal(1, tensor.Lengths[0]); Assert.Equal(2, tensor.Lengths[1]); - Assert.Equal(2, tensor.Strides[0]); + Assert.Equal(0, tensor.Strides[0]); Assert.Equal(1, tensor.Strides[1]); tensor = Tensor.Unsqueeze(tensor, 0); @@ -2224,8 +2222,8 @@ public static void TensorUnsqueezeTest() Assert.Equal(1, tensor.Lengths[0]); Assert.Equal(1, tensor.Lengths[1]); Assert.Equal(2, tensor.Lengths[2]); - Assert.Equal(2, tensor.Strides[0]); - Assert.Equal(2, tensor.Strides[1]); + Assert.Equal(0, tensor.Strides[0]); + Assert.Equal(0, tensor.Strides[1]); Assert.Equal(1, tensor.Strides[2]); tensor = Tensor.Unsqueeze(tensor, 0); @@ -2234,12 +2232,12 @@ public static void TensorUnsqueezeTest() Assert.Equal(1, tensor.Lengths[1]); Assert.Equal(1, tensor.Lengths[2]); Assert.Equal(2, tensor.Lengths[3]); - Assert.Equal(2, tensor.Strides[0]); - Assert.Equal(2, tensor.Strides[1]); - Assert.Equal(2, tensor.Strides[2]); + Assert.Equal(0, tensor.Strides[0]); + Assert.Equal(0, tensor.Strides[1]); + Assert.Equal(0, tensor.Strides[2]); Assert.Equal(1, tensor.Strides[3]); - tensor = Tensor.Create([2], false); + tensor = Tensor.Create((ReadOnlySpan)[2], false); Assert.Equal(1, tensor.Rank); Assert.Equal(2, tensor.Lengths[0]); @@ -2248,7 +2246,7 @@ public static void TensorUnsqueezeTest() Assert.Equal(2, tensor.Lengths[0]); Assert.Equal(1, tensor.Lengths[1]); - tensor = Tensor.Create([2], false); + tensor = Tensor.Create((ReadOnlySpan)[2], false); Assert.Equal(1, tensor.Rank); Assert.Equal(2, tensor.Lengths[0]);