diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs index d5f7382046887f..0da8b6dfcdec2a 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs @@ -6,72 +6,153 @@ namespace System.Numerics.Tensors /// Performs primitive tensor operations over spans of memory. public static partial class TensorPrimitives { - /// Computes the element-wise result of: MathF.Abs(). + /// Computes the element-wise absolute value of each single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = MathF.Abs([i]). + /// + /// + /// This method effectively computes [i] = MathF.Abs([i]). + /// + /// + /// The absolute value of a is its numeric value without its sign. For example, the absolute value of both 1.2e-03 and -1.2e03 is 1.2e03. + /// + /// + /// If a value is equal to or , the result stored into the corresponding destination location is set to . + /// If a value is equal to , the result stored into the corresponding destination location is the original NaN value with the sign bit removed. + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// public static void Abs(ReadOnlySpan x, Span destination) => InvokeSpanIntoSpan(x, destination); - /// Computes the element-wise result of: + . + /// Computes the element-wise addition of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = [i] + [i]. + /// + /// + /// This method effectively computes [i] = [i] + [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static unsafe void Add(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the element-wise result of: + . + /// Computes the element-wise addition of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = [i] + . + /// + /// + /// This method effectively computes [i] = [i] + . + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Add(ReadOnlySpan x, float y, Span destination) => InvokeSpanScalarIntoSpan(x, y, destination); - /// Computes the element-wise result of: ( + ) * . + /// Computes the element-wise result of ( + ) * for the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of and the length of . /// Destination is too short. - /// This method effectively does [i] = ([i] + [i]) * [i]. + /// + /// + /// This method effectively computes [i] = ([i] + [i]) * [i]. + /// + /// + /// , , and may overlap, but none of them may overlap with ; if they do, behavior is undefined. + /// + /// + /// If any of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan multiplier, Span destination) => InvokeSpanSpanSpanIntoSpan(x, y, multiplier, destination); - /// Computes the element-wise result of: ( + ) * . + /// Computes the element-wise result of ( + ) * for the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a scalar. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = ([i] + [i]) * . + /// + /// + /// This method effectively computes [i] = ([i] + [i]) * . + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If any of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, float multiplier, Span destination) => InvokeSpanSpanScalarIntoSpan(x, y, multiplier, destination); - /// Computes the element-wise result of: ( + ) * . + /// Computes the element-wise result of ( + ) * for the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = ([i] + ) * [i]. + /// + /// + /// This method effectively computes [i] = ([i] + ) * [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If any of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void AddMultiply(ReadOnlySpan x, float y, ReadOnlySpan multiplier, Span destination) => InvokeSpanScalarSpanIntoSpan(x, y, multiplier, destination); - /// Computes the element-wise result of: cosh(). + /// Computes the element-wise hyperbolic cosine of each single-precision floating-point radian angle in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Cosh([i]). + /// + /// + /// This method effectively computes [i] = .Cosh([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value is equal to or , the result stored into the corresponding destination location is set to . + /// If a value is equal to , the result stored into the corresponding destination location is also NaN. + /// + /// + /// The angles in x must be in radians. Use or multiply by /180 to convert degrees to radians. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Cosh(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) @@ -85,12 +166,25 @@ public static void Cosh(ReadOnlySpan x, Span destination) } } - /// Computes the cosine similarity between two non-zero vectors. + /// Computes the cosine similarity between the two specified non-empty, equal-length tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. - /// The cosine similarity between the two vectors. - /// Length of '' must be same as length of ''. - /// '' and '' must not be empty. + /// The cosine similarity of the two tensors. + /// Length of must be same as length of . + /// and must not be empty. + /// + /// + /// This method effectively computes TensorPrimitives.Dot(x, y) / (MathF.Sqrt(TensorPrimitives.SumOfSquares(x)) * MathF.Sqrt(TensorPrimitives.SumOfSquares(y)). + /// + /// + /// If any element in either input tensor is equal to , , or , + /// NaN is returned. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float CosineSimilarity(ReadOnlySpan x, ReadOnlySpan y) { if (x.IsEmpty) @@ -106,14 +200,30 @@ public static float CosineSimilarity(ReadOnlySpan x, ReadOnlySpan return CosineSimilarityCore(x, y); } - /// - /// Compute the distance between two points in Euclidean space. - /// + /// Computes the distance between two points, specified as non-empty, equal-length tensors of single-precision floating-point numbers, in Euclidean space. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The Euclidean distance. - /// Length of '' must be same as length of ''. - /// '' and '' must not be empty. + /// Length of must be same as length of . + /// and must not be empty. + /// + /// + /// This method effectively computes the equivalent of: + /// + /// Span<float> difference = ...; + /// TensorPrimitives.Subtract(x, y, difference); + /// float result = MathF.Sqrt(TensorPrimitives.SumOfSquares(difference)); + /// + /// but without requiring additional temporary storage for the intermediate differences. + /// + /// + /// If any element in either input tensor is equal to , NaN is returned. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float Distance(ReadOnlySpan x, ReadOnlySpan y) { if (x.IsEmpty) @@ -129,33 +239,69 @@ public static float Distance(ReadOnlySpan x, ReadOnlySpan y) return MathF.Sqrt(Aggregate(x, y)); } - /// Computes the element-wise result of: / . + /// Computes the element-wise division of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = [i] / . + /// + /// + /// This method effectively computes [i] = [i] / [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Divide(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the element-wise result of: / . + /// Computes the element-wise division of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = [i] / . + /// + /// + /// This method effectively computes [i] = [i] / . + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Divide(ReadOnlySpan x, float y, Span destination) => InvokeSpanScalarIntoSpan(x, y, destination); - /// - /// A mathematical operation that takes two vectors and returns a scalar. - /// + /// Computes the dot product of two tensors containing single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The dot product. - /// Length of '' must be same as length of ''. - public static float Dot(ReadOnlySpan x, ReadOnlySpan y) // BLAS1: dot + /// Length of must be same as length of . + /// + /// + /// This method effectively computes the equivalent of: + /// + /// Span<float> products = ...; + /// TensorPrimitives.Multiply(x, y, products); + /// float result = TensorPrimitives.Sum(products); + /// + /// but without requiring additional temporary storage for the intermediate products. It corresponds to the dot method defined by BLAS1. + /// + /// + /// If any of the input elements is equal to , the resulting value is also NaN. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static float Dot(ReadOnlySpan x, ReadOnlySpan y) { if (x.Length != y.Length) { @@ -165,11 +311,26 @@ public static float Dot(ReadOnlySpan x, ReadOnlySpan y) // BLAS1: return Aggregate(x, y); } - /// Computes the element-wise result of: pow(e, ). + /// Computes the element-wise result of raising e to the single-precision floating-point number powers in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Exp([i]). + /// + /// + /// This method effectively computes [i] = .Exp([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value equals or , the result stored into the corresponding destination location is set to NaN. + /// If a value equals , the result stored into the corresponding destination location is set to 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Exp(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) @@ -183,9 +344,19 @@ public static void Exp(ReadOnlySpan x, Span destination) } } - /// Computes the index of the maximum element in . + /// Searches for the index of the largest single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The index of the maximum element in , or -1 if is empty. + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximum` function. If any value equal to + /// is present, the index of the first is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static unsafe int IndexOfMax(ReadOnlySpan x) { int result = -1; @@ -196,11 +367,6 @@ public static unsafe int IndexOfMax(ReadOnlySpan x) for (int i = 0; i < x.Length; i++) { - // This matches the IEEE 754:2019 `maximum` function. - // It propagates NaN inputs back to the caller and - // otherwise returns the greater of the inputs. - // It treats +0 as greater than -0 as per the specification. - float current = x[i]; if (current != max) @@ -227,10 +393,20 @@ public static unsafe int IndexOfMax(ReadOnlySpan x) return result; } - /// Computes the index of the element in with the maximum magnitude. + /// Searches for the index of the single-precision floating-point number with the largest magnitude in the specified tensor. /// The tensor, represented as a span. - /// The index of the element with the maximum magnitude, or -1 if is empty. - /// This method corresponds to the iamax method defined by BLAS1. + /// The index of the element in with the largest magnitude (absolute value), or -1 if is empty. + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitude` function. If any value equal to + /// is present, the index of the first is returned. If two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static unsafe int IndexOfMaxMagnitude(ReadOnlySpan x) { int result = -1; @@ -242,11 +418,6 @@ public static unsafe int IndexOfMaxMagnitude(ReadOnlySpan x) for (int i = 0; i < x.Length; i++) { - // This matches the IEEE 754:2019 `maximumMagnitude` function. - // It propagates NaN inputs back to the caller and - // otherwise returns the input with a greater magnitude. - // It treats +0 as greater than -0 as per the specification. - float current = x[i]; float currentMag = Math.Abs(current); @@ -276,9 +447,19 @@ public static unsafe int IndexOfMaxMagnitude(ReadOnlySpan x) return result; } - /// Computes the index of the minimum element in . + /// Searches for the index of the smallest single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The index of the minimum element in , or -1 if is empty. + /// + /// + /// The determination of the minimum element matches the IEEE 754:2019 `minimum` function. If any value equal to + /// is present, the index of the first is returned. Negative 0 is considered smaller than positive 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static unsafe int IndexOfMin(ReadOnlySpan x) { int result = -1; @@ -289,11 +470,6 @@ public static unsafe int IndexOfMin(ReadOnlySpan x) for (int i = 0; i < x.Length; i++) { - // This matches the IEEE 754:2019 `minimum` function. - // It propagates NaN inputs back to the caller and - // otherwise returns the lesser of the inputs. - // It treats +0 as greater than -0 as per the specification. - float current = x[i]; if (current != min) @@ -320,9 +496,20 @@ public static unsafe int IndexOfMin(ReadOnlySpan x) return result; } - /// Computes the index of the element in with the minimum magnitude. + /// Searches for the index of the single-precision floating-point number with the smallest magnitude in the specified tensor. /// The tensor, represented as a span. - /// The index of the element with the minimum magnitude, or -1 if is empty. + /// The index of the element in with the smallest magnitude (absolute value), or -1 if is empty. + /// + /// + /// The determination of the minimum magnitude matches the IEEE 754:2019 `minimumMagnitude` function. If any value equal to + /// is present, the index of the first is returned. If two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static unsafe int IndexOfMinMagnitude(ReadOnlySpan x) { int result = -1; @@ -334,11 +521,6 @@ public static unsafe int IndexOfMinMagnitude(ReadOnlySpan x) for (int i = 0; i < x.Length; i++) { - // This matches the IEEE 754:2019 `minimumMagnitude` function - // It propagates NaN inputs back to the caller and - // otherwise returns the input with a lesser magnitude. - // It treats +0 as greater than -0 as per the specification. - float current = x[i]; float currentMag = Math.Abs(current); @@ -368,11 +550,28 @@ public static unsafe int IndexOfMinMagnitude(ReadOnlySpan x) return result; } - /// Computes the element-wise result of: ln(). + /// Computes the element-wise natural (base e) logarithm of single-precision floating-point numbers in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Log([i]). + /// + /// + /// This method effectively computes [i] = .Log([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value equals 0, the result stored into the corresponding destination location is set to . + /// If a value is negative or equal to , the result stored into the corresponding destination location is set to NaN. + /// If a value is positive infinity, the result stored into the corresponding destination location is set to . + /// Otherwise, if a value is positive, its natural logarithm is stored into the corresponding destination location. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Log(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) @@ -386,11 +585,28 @@ public static void Log(ReadOnlySpan x, Span destination) } } - /// Computes the element-wise result of: log2(). + /// Computes the element-wise base 2 logarithm of single-precision floating-point numbers in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Log2([i]). + /// + /// + /// This method effectively computes [i] = .Log2([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value equals 0, the result stored into the corresponding destination location is set to . + /// If a value is negative or equal to , the result stored into the corresponding destination location is set to NaN. + /// If a value is positive infinity, the result stored into the corresponding destination location is set to . + /// Otherwise, if a value is positive, its natural logarithm is stored into the corresponding destination location. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Log2(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) @@ -404,153 +620,329 @@ public static void Log2(ReadOnlySpan x, Span destination) } } - /// Computes the maximum element in . + /// Searches for the largest single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The maximum element in . - /// Length of '' must be greater than zero. + /// Length of must be greater than zero. + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximum` function. If any value equal to + /// is present, the first is returned. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float Max(ReadOnlySpan x) => MinMaxCore(x); - /// Computes the element-wise result of: MathF.Max(, ). + /// Computes the element-wise maximum of the single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = MathF.Max([i], [i]). + /// + /// + /// This method effectively computes [i] = MathF.Max([i], [i]). + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximum` function. If either value is equal to , + /// that value is stored as the result. Positive 0 is considered greater than negative 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Max(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the maximum magnitude of any element in . + /// Searches for the single-precision floating-point number with the largest magnitude in the specified tensor. /// The tensor, represented as a span. - /// The maximum magnitude of any element in . - /// Length of '' must be greater than zero. + /// The element in with the largest magnitude (absolute value). + /// Length of must be greater than zero. + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitude` function. If any value equal to + /// is present, the first is returned. If two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float MaxMagnitude(ReadOnlySpan x) => MinMaxCore(x); - /// Computes the element-wise result of: MathF.MaxMagnitude(, ). + /// Computes the element-wise single-precision floating-point number with the largest magnitude in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = MathF.MaxMagnitude([i], [i]). + /// This method effectively computes [i] = MathF.MaxMagnitude([i], [i]). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `maximumMagnitude` function. If either value is equal to , + /// that value is stored as the result. If the two values have the same magnitude and one is positive and the other is negative, + /// the positive value is considered to have the larger magnitude. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void MaxMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the minimum element in . + /// Searches for the smallest single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The minimum element in . - /// Length of '' must be greater than zero. + /// Length of must be greater than zero. + /// + /// + /// The determination of the minimum element matches the IEEE 754:2019 `minimum` function. If any value is equal to + /// is present, the first is returned. Negative 0 is considered smaller than positive 0. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float Min(ReadOnlySpan x) => MinMaxCore(x); - /// Computes the element-wise result of: MathF.Min(, ). + /// Computes the element-wise minimum of the single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = MathF.Min([i], [i]). + /// + /// + /// This method effectively computes [i] = MathF.Max([i], [i]). + /// + /// + /// The determination of the maximum element matches the IEEE 754:2019 `maximum` function. If either value is equal to , + /// that value is stored as the result. Positive 0 is considered greater than negative 0. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Min(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the minimum magnitude of any element in . + /// Searches for the single-precision floating-point number with the smallest magnitude in the specified tensor. /// The tensor, represented as a span. - /// The minimum magnitude of any element in . - /// Length of '' must be greater than zero. + /// The element in with the smallest magnitude (absolute value). + /// Length of must be greater than zero. + /// + /// + /// The determination of the minimum magnitude matches the IEEE 754:2019 `minimumMagnitude` function. If any value equal to + /// is present, the first is returned. If two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float MinMagnitude(ReadOnlySpan x) => MinMaxCore(x); - /// Computes the element-wise result of: MathF.MinMagnitude(, ). + /// Computes the element-wise single-precision floating-point number with the smallest magnitude in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = MathF.MinMagnitude([i], [i]). + /// This method effectively computes [i] = MathF.MinMagnitude([i], [i]). + /// + /// + /// The determination of the maximum magnitude matches the IEEE 754:2019 `minimumMagnitude` function. If either value is equal to , + /// that value is stored as the result. If the two values have the same magnitude and one is positive and the other is negative, + /// the negative value is considered to have the smaller magnitude. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void MinMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the element-wise result of: * . + /// Computes the element-wise product of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = [i] * . + /// + /// + /// This method effectively computes [i] = [i] * [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Multiply(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the element-wise result of: * . + /// Computes the element-wise product of single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The destination tensor, represented as a span. /// Destination is too short. /// - /// This method effectively does [i] = [i] * . - /// This method corresponds to the scal method defined by BLAS1. + /// + /// This method effectively computes [i] = [i] * . + /// It corresponds to the scal method defined by BLAS1. + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// /// public static void Multiply(ReadOnlySpan x, float y, Span destination) => InvokeSpanScalarIntoSpan(x, y, destination); - /// Computes the element-wise result of: ( * ) + . + /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The third tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of and length of . /// Destination is too short. - /// This method effectively does [i] = ([i] * [i]) + [i]. + /// + /// + /// This method effectively computes [i] = ([i] * [i]) + [i]. + /// + /// + /// , , and may overlap, but none of them may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan addend, Span destination) => InvokeSpanSpanSpanIntoSpan(x, y, addend, destination); - /// Computes the element-wise result of: ( * ) + . + /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. /// The second tensor, represented as a span. - /// The third tensor, represented as a span. + /// The third tensor, represented as a scalar. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. /// - /// This method effectively does [i] = ([i] * [i]) + . - /// This method corresponds to the axpy method defined by BLAS1. + /// + /// This method effectively computes [i] = ([i] * [i]) + . + /// It corresponds to the axpy method defined by BLAS1. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// /// public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, float addend, Span destination) => InvokeSpanSpanScalarIntoSpan(x, y, addend, destination); - /// Computes the element-wise result of: ( * ) + . + /// Computes the element-wise result of ( * ) * for the specified tensors of single-precision floating-point numbers. /// The first tensor, represented as a span. - /// The second tensor, represented as a span. + /// The second tensor, represented as a scalar. /// The third tensor, represented as a span. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = ([i] * ) + [i]. + /// + /// + /// This method effectively computes [i] = ([i] * ) + [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void MultiplyAdd(ReadOnlySpan x, float y, ReadOnlySpan addend, Span destination) => InvokeSpanScalarSpanIntoSpan(x, y, addend, destination); - /// Computes the element-wise result of: -. + /// Computes the element-wise negation of each single-precision floating-point number in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = -[i]. + /// + /// + /// This method effectively computes [i] = -[i]. + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If any of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Negate(ReadOnlySpan x, Span destination) => InvokeSpanIntoSpan(x, destination); - /// - /// A mathematical operation that takes a vector and returns the L2 norm. - /// + /// Computes the Euclidean norm of the specified tensor of single-precision floating-point numbers. /// The first tensor, represented as a span. - /// The L2 norm. - public static float Norm(ReadOnlySpan x) => // BLAS1: nrm2 - MathF.Sqrt(Aggregate(x)); + /// The norm. + /// + /// + /// This method effectively computes MathF.Sqrt(TensorPrimitives.SumOfSquares(x)). + /// This is often referred to as the Euclidean norm or L2 norm. + /// It corresponds to the nrm2 method defined by BLAS1. + /// + /// + /// If any of the input values is equal to , the result value is also NaN. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// + public static float Norm(ReadOnlySpan x) => + MathF.Sqrt(SumOfSquares(x)); - /// Computes the product of all elements in . + /// Computes the product of all elements in the specified non-empty tensor of single-precision floating-point numbers. /// The tensor, represented as a span. /// The result of multiplying all elements in . - /// Length of '' must be greater than zero. + /// Length of must be greater than zero. + /// + /// + /// If any of the input values is equal to , the result value is also NaN. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float Product(ReadOnlySpan x) { if (x.IsEmpty) @@ -561,13 +953,27 @@ public static float Product(ReadOnlySpan x) return Aggregate(x); } - /// Computes the product of the element-wise result of: - . + /// Computes the product of the element-wise differences of the single-precision floating-point numbers in the specified non-empty tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The result of multiplying the element-wise subtraction of the elements in the second tensor from the first tensor. /// Length of both input spans must be greater than zero. /// and must have the same length. - /// This method effectively does .Product(.Subtract(, )). + /// + /// + /// This method effectively computes: + /// + /// Span<float> differences = ...; + /// TensorPrimitives.Subtract(x, y, differences); + /// float result = TensorPrimitives.Product(differences); + /// + /// but without requiring additional temporary storage for the intermediate differences. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float ProductOfDifferences(ReadOnlySpan x, ReadOnlySpan y) { if (x.IsEmpty) @@ -583,13 +989,27 @@ public static float ProductOfDifferences(ReadOnlySpan x, ReadOnlySpan(x, y); } - /// Computes the product of the element-wise result of: + . + /// Computes the product of the element-wise sums of the single-precision floating-point numbers in the specified non-empty tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a span. /// The result of multiplying the element-wise additions of the elements in each tensor. /// Length of both input spans must be greater than zero. /// and must have the same length. - /// This method effectively does .Product(.Add(, )). + /// + /// + /// This method effectively computes: + /// + /// Span<float> sums = ...; + /// TensorPrimitives.Add(x, y, sums); + /// float result = TensorPrimitives.Product(sums); + /// + /// but without requiring additional temporary storage for the intermediate sums. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float ProductOfSums(ReadOnlySpan x, ReadOnlySpan y) { if (x.IsEmpty) @@ -605,13 +1025,23 @@ public static float ProductOfSums(ReadOnlySpan x, ReadOnlySpan y) return Aggregate(x, y); } - /// - /// A function that takes a real number and returns a value between 0 and 1. - /// - /// The first tensor, represented as a span. + /// Computes the element-wise sigmoid function on the specified non-empty tensor of single-precision floating-point numbers. + /// The tensor, represented as a span. /// The destination tensor. /// Destination is too short. - /// '' must not be empty. + /// must not be empty. + /// + /// + /// This method effectively computes [i] = 1f / (1f + .Exp(-[i])). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Sigmoid(ReadOnlySpan x, Span destination) { if (x.IsEmpty) @@ -626,15 +1056,33 @@ public static void Sigmoid(ReadOnlySpan x, Span destination) for (int i = 0; i < x.Length; i++) { - destination[i] = 1f / (1 + MathF.Exp(-x[i])); + destination[i] = 1f / (1f + MathF.Exp(-x[i])); } } - /// Computes the element-wise result of: sinh(). + /// Computes the element-wise hyperbolic sine of each single-precision floating-point radian angle in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Sinh([i]). + /// + /// + /// This method effectively computes [i] = .Sinh([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value is equal to , , or , + /// the corresponding destination location is set to that value. + /// + /// + /// The angles in x must be in radians. Use or multiply by /180 to convert degrees to radians. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Sinh(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) @@ -648,13 +1096,24 @@ public static void Sinh(ReadOnlySpan x, Span destination) } } - /// - /// A function that takes a collection of real numbers and returns a probability distribution. - /// - /// The first tensor, represented as a span. + /// Computes the softmax function over the specified non-empty tensor of single-precision floating-point numbers. + /// The tensor, represented as a span. /// The destination tensor. /// Destination is too short. - /// '' must not be empty. + /// must not be empty. + /// + /// + /// This method effectively computes a sum of MathF.Exp(x[i]) for all elements in . + /// It then effectively computes [i] = MathF.Exp([i]) / sum. + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void SoftMax(ReadOnlySpan x, Span destination) { if (x.IsEmpty) @@ -680,53 +1139,126 @@ public static void SoftMax(ReadOnlySpan x, Span destination) } } - /// Computes the element-wise result of: - . + /// Computes the element-wise difference between single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The destination tensor, represented as a span. - /// Length of '' must be same as length of ''. + /// Length of must be same as length of . /// Destination is too short. - /// This method effectively does [i] = [i] - [i]. + /// + /// + /// This method effectively computes [i] = [i] - [i]. + /// + /// + /// and may overlap, but neither may overlap with ; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Subtract(ReadOnlySpan x, ReadOnlySpan y, Span destination) => InvokeSpanSpanIntoSpan(x, y, destination); - /// Computes the element-wise result of: - . + /// Computes the element-wise difference between single-precision floating-point numbers in the specified tensors. /// The first tensor, represented as a span. /// The second tensor, represented as a scalar. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = [i] - . + /// + /// + /// This method effectively computes [i] = [i] - . + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If either of the element-wise input values is equal to , the resulting element-wise value is also NaN. + /// + /// public static void Subtract(ReadOnlySpan x, float y, Span destination) => InvokeSpanScalarIntoSpan(x, y, destination); - /// Computes the sum of all elements in . + /// Computes the sum of all elements in the specified tensor of single-precision floating-point numbers. /// The tensor, represented as a span. /// The result of adding all elements in , or zero if is empty. + /// + /// + /// If any of the values in the input is equal to , the result is also NaN. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float Sum(ReadOnlySpan x) => Aggregate(x); - /// Computes the sum of the absolute values of every element in . + /// Computes the sum of the absolute values of every element in the specified tensor of single-precision floating-point numbers. /// The tensor, represented as a span. /// The result of adding the absolute value of every element in , or zero if is empty. /// - /// This method effectively does .Sum(.Abs()). - /// This method corresponds to the asum method defined by BLAS1. + /// + /// This method effectively computes: + /// + /// Span<float> absoluteValues = ...; + /// TensorPrimitives.Abs(x, absoluteValues); + /// float result = TensorPrimitives.Sum(absoluteValues); + /// + /// but without requiring intermediate storage for the absolute values. It corresponds to the asum method defined by BLAS1. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// /// public static float SumOfMagnitudes(ReadOnlySpan x) => Aggregate(x); - /// Computes the sum of the squares of every element in . + /// Computes the sum of the square of every element in the specified tensor of single-precision floating-point numbers. /// The tensor, represented as a span. - /// The result of adding every element in multiplied by itself, or zero if is empty. - /// This method effectively does .Sum(.Multiply(, )). + /// The result of adding the square of every element in , or zero if is empty. + /// + /// + /// This method effectively computes: + /// + /// Span<float> squaredValues = ...; + /// TensorPrimitives.Multiply(x, x, squaredValues); + /// float result = TensorPrimitives.Sum(squaredValues); + /// + /// but without requiring intermediate storage for the squared values. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static float SumOfSquares(ReadOnlySpan x) => Aggregate(x); - /// Computes the element-wise result of: tanh(). + /// Computes the element-wise hyperbolic tangent of each single-precision floating-point radian angle in the specified tensor. /// The tensor, represented as a span. /// The destination tensor, represented as a span. /// Destination is too short. - /// This method effectively does [i] = .Tanh([i]). + /// + /// + /// This method effectively computes [i] = .Tanh([i]). + /// + /// + /// and may not overlap; if they do, behavior is undefined. + /// + /// + /// If a value is equal to , the corresponding destination location is set to -1. + /// If a value is equal to , the corresponding destination location is set to 1. + /// If a value is equal to , the corresponding destination location is set to NaN. + /// + /// + /// The angles in x must be in radians. Use or multiply by /180 to convert degrees to radians. + /// + /// + /// This method may call into the underlying C runtime or employ instructions specific to the current architecture. Exact results may differ between different + /// operating systems or architectures. + /// + /// public static void Tanh(ReadOnlySpan x, Span destination) { if (x.Length > destination.Length) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.netcore.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.netcore.cs index d210d9f0f82404..bed07eedfefd1e 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.netcore.cs @@ -19,6 +19,11 @@ public static partial class TensorPrimitives /// The source span from which to copy values. /// The destination span into which the converted values should be written. /// Destination is too short. + /// + /// + /// This method effectively computes [i] = (Half)[i]. + /// + /// public static void ConvertToHalf(ReadOnlySpan source, Span destination) { if (source.Length > destination.Length) @@ -39,6 +44,11 @@ public static void ConvertToHalf(ReadOnlySpan source, Span destinat /// The source span from which to copy values. /// The destination span into which the converted values should be written. /// Destination is too short. + /// + /// + /// This method effectively computes [i] = (float)[i]. + /// + /// public static void ConvertToSingle(ReadOnlySpan source, Span destination) { if (source.Length > destination.Length) @@ -1908,11 +1918,11 @@ public static Vector512 Invoke(Vector512 x, Vector512 y) private readonly struct MultiplyAddOperator : ITernaryOperator { - public static float Invoke(float x, float y, float z) => MathF.FusedMultiplyAdd(x, y, z); - public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z) => FusedMultiplyAdd(x, y, z); - public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z) => FusedMultiplyAdd(x, y, z); + public static float Invoke(float x, float y, float z) => (x * y) + z; + public static Vector128 Invoke(Vector128 x, Vector128 y, Vector128 z) => (x * y) + z; + public static Vector256 Invoke(Vector256 x, Vector256 y, Vector256 z) => (x * y) + z; #if NET8_0_OR_GREATER - public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z) => FusedMultiplyAdd(x, y, z); + public static Vector512 Invoke(Vector512 x, Vector512 y, Vector512 z) => (x * y) + z; #endif }