diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs index d3c31753c42ba8..9475c3390558f5 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs @@ -487,7 +487,7 @@ public static void ResizeTo(scoped in System.Numerics.Tensors.Tensor tenso public static ref readonly System.Numerics.Tensors.TensorSpan StackAlongDimension(scoped System.ReadOnlySpan> tensors, in System.Numerics.Tensors.TensorSpan destination, int dimension) { throw null; } public static System.Numerics.Tensors.Tensor Stack(params scoped System.ReadOnlySpan> tensors) { throw null; } public static ref readonly System.Numerics.Tensors.TensorSpan Stack(scoped in System.ReadOnlySpan> tensors, in System.Numerics.Tensors.TensorSpan destination) { throw null; } - public static T StdDev(in System.Numerics.Tensors.ReadOnlyTensorSpan x) where T : System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static T StdDev(in System.Numerics.Tensors.ReadOnlyTensorSpan x) where T : System.Numerics.IFloatingPoint, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IRootFunctions { throw null; } public static System.Numerics.Tensors.Tensor Subtract(in System.Numerics.Tensors.ReadOnlyTensorSpan x, in System.Numerics.Tensors.ReadOnlyTensorSpan y) where T : System.Numerics.ISubtractionOperators { throw null; } public static ref readonly System.Numerics.Tensors.TensorSpan Subtract(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan x, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan y, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ISubtractionOperators { throw null; } public static System.Numerics.Tensors.Tensor Subtract(in System.Numerics.Tensors.ReadOnlyTensorSpan x, T y) where T : System.Numerics.ISubtractionOperators { throw null; } diff --git a/src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml b/src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml index ae2ea3d401a7b1..d05601550864ea 100644 --- a/src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Numerics.Tensors/src/CompatibilitySuppressions.xml @@ -253,4 +253,18 @@ lib/net9.0/System.Numerics.Tensors.dll true + + CP0021 + M:System.Numerics.Tensors.Tensor.StdDev``1(System.Numerics.Tensors.ReadOnlyTensorSpan{``0}@)``0:T:System.Numerics.IRootFunctions{``0} + lib/net8.0/System.Numerics.Tensors.dll + lib/net8.0/System.Numerics.Tensors.dll + true + + + CP0021 + M:System.Numerics.Tensors.Tensor.StdDev``1(System.Numerics.Tensors.ReadOnlyTensorSpan{``0}@)``0:T:System.Numerics.IRootFunctions{``0} + lib/net9.0/System.Numerics.Tensors.dll + lib/net9.0/System.Numerics.Tensors.dll + true + \ No newline at end of file diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs index 5ba164337bfc91..84c933226fb2a1 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs @@ -3512,26 +3512,15 @@ public static ref readonly TensorSpan StackAlongDimension(scoped ReadOnlyS /// The to take the standard deviation of. /// representing the standard deviation. public static T StdDev(in ReadOnlyTensorSpan x) - where T : IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity + where T : IFloatingPoint, IAdditionOperators, IAdditiveIdentity, IRootFunctions { T mean = Average(x); - Span span = MemoryMarshal.CreateSpan(ref x._reference, (int)x._shape._memoryLength); - Span output = new T[x.FlattenedLength]; - TensorPrimitives.Subtract(span, mean, output); - TensorPrimitives.Abs(output, output); - TensorPrimitives.Pow((ReadOnlySpan)output, T.CreateChecked(2), output); - T sum = TensorPrimitives.Sum((ReadOnlySpan)output); - T variance = sum / T.CreateChecked(x._shape._memoryLength); - - if (typeof(T) == typeof(float)) - { - return T.CreateChecked(MathF.Sqrt(float.CreateChecked(variance))); - } - if (typeof(T) == typeof(double)) - { - return T.CreateChecked(Math.Sqrt(double.CreateChecked(variance))); - } - return T.Pow(variance, T.CreateChecked(0.5)); + Tensor temp = CreateUninitialized(x.Lengths); + Subtract(x, mean, temp); + Abs(temp, temp); + T sum = SumOfSquares(temp); + T variance = sum / T.CreateChecked(x.FlattenedLength); + return T.Sqrt(variance); } #endregion @@ -6664,6 +6653,19 @@ public static T Sum(scoped in ReadOnlyTensorSpan x) } #endregion + #region SumOfSquares + /// + /// Sums the squared elements of the specified tensor. + /// + /// Tensor to sum squares of + /// + internal static T SumOfSquares(scoped in ReadOnlyTensorSpan x) + where T : IAdditionOperators, IAdditiveIdentity, IMultiplyOperators + { + return TensorPrimitivesHelperSpanInTOut(x, TensorPrimitives.SumOfSquares); + } + #endregion + #region Tan /// Computes the element-wise tangent of the value in the specified tensor. /// The to take the sin of. diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs index 165779fe329a61..607d09788db1ce 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -1124,6 +1124,15 @@ public static void TensorStdDevTests() Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); Assert.Equal(StdDev([0, 1, 2, 3]), Tensor.StdDev(t0), .1); + + // Test that non-contiguous calculations work + Tensor fourByFour = Tensor.Create([4, 4]); + fourByFour[[0, 0]] = 1f; + fourByFour[[0, 1]] = 1f; + fourByFour[[1, 0]] = 1f; + fourByFour[[1, 1]] = 1f; + ReadOnlyTensorSpan upperLeft = fourByFour.AsReadOnlyTensorSpan().Slice([0..2, 0..2]); + Assert.Equal(0f, Tensor.StdDev(upperLeft)); } public static float StdDev(float[] values)