diff --git a/src/libraries/System.Numerics.Tensors/System.Numerics.Tensors.sln b/src/libraries/System.Numerics.Tensors/System.Numerics.Tensors.sln
index cc3000d60ef88..015b65250931a 100644
--- a/src/libraries/System.Numerics.Tensors/System.Numerics.Tensors.sln
+++ b/src/libraries/System.Numerics.Tensors/System.Numerics.Tensors.sln
@@ -1,18 +1,34 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34205.153
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{9F20CEA1-2216-4432-BBBD-F01E05D17F23}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.Numerics", "..\Microsoft.Bcl.Numerics\ref\Microsoft.Bcl.Numerics.csproj", "{D311ABE4-10A9-4BB1-89CE-6358C55501A8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.Numerics", "..\Microsoft.Bcl.Numerics\src\Microsoft.Bcl.Numerics.csproj", "{1578185F-C4FA-4866-936B-E62AAEDD03B7}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Numerics.Tensors", "ref\System.Numerics.Tensors.csproj", "{21CB448A-3882-4337-B416-D1A3E0BCFFC5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Numerics.Tensors", "src\System.Numerics.Tensors.csproj", "{848DD000-3D22-4A25-A9D9-05AFF857A116}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Numerics.Tensors.Tests", "tests\System.Numerics.Tensors.Tests.csproj", "{4AF6A02D-82C8-4898-9EDF-01F107C25061}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "..\System.Runtime.InteropServices\gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{8CA7C982-3EE4-4BCE-9493-7A63556736D3}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryImportGenerator", "..\System.Runtime.InteropServices\gen\LibraryImportGenerator\LibraryImportGenerator.csproj", "{4588351F-4233-4957-B84C-7F8E22B8888A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.SourceGeneration", "..\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{DB954E01-898A-4FE2-A3AA-180D041AB08F}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILLink.CodeFixProvider", "..\..\tools\illink\src\ILLink.CodeFix\ILLink.CodeFixProvider.csproj", "{04FC0651-B9D0-448A-A28B-11B1D4A897F4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILLink.RoslynAnalyzer", "..\..\tools\illink\src\ILLink.RoslynAnalyzer\ILLink.RoslynAnalyzer.csproj", "{683A7D28-CC55-4375-848D-E659075ECEE4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILLink.Tasks", "..\..\tools\illink\src\ILLink.Tasks\ILLink.Tasks.csproj", "{1CBEAEA8-2CA1-4B07-9930-35A785205852}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Linker", "..\..\tools\illink\src\linker\Mono.Linker.csproj", "{BA7828B1-7953-47A0-AE5A-E22B501C4BD0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Linker", "..\..\tools\illink\src\linker\ref\Mono.Linker.csproj", "{57E57290-3A6A-43F8-8764-D4DC8151F89C}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DE94CA7D-BB10-4865-85A6-6B694631247F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{6BC42E6D-848C-4533-B715-F116E7DB3610}"
@@ -21,6 +37,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{AB415F5A-75E
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{083161E5-6049-4D84-9739-9D7797D7117D}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{841A2FA4-A95F-4612-A8B9-AD2EF769BC71}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DF0561A1-3AB8-4B51-AFB4-392EE1DD6247}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{7AC4B2C7-A55C-4C4F-9B02-77F5CBFFF4AB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{F9C2AAB1-C7B0-4E43-BB18-4FB16F6E272B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -31,6 +55,14 @@ Global
{9F20CEA1-2216-4432-BBBD-F01E05D17F23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F20CEA1-2216-4432-BBBD-F01E05D17F23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F20CEA1-2216-4432-BBBD-F01E05D17F23}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D311ABE4-10A9-4BB1-89CE-6358C55501A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D311ABE4-10A9-4BB1-89CE-6358C55501A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D311ABE4-10A9-4BB1-89CE-6358C55501A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D311ABE4-10A9-4BB1-89CE-6358C55501A8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1578185F-C4FA-4866-936B-E62AAEDD03B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1578185F-C4FA-4866-936B-E62AAEDD03B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1578185F-C4FA-4866-936B-E62AAEDD03B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1578185F-C4FA-4866-936B-E62AAEDD03B7}.Release|Any CPU.Build.0 = Release|Any CPU
{21CB448A-3882-4337-B416-D1A3E0BCFFC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21CB448A-3882-4337-B416-D1A3E0BCFFC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21CB448A-3882-4337-B416-D1A3E0BCFFC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -43,10 +75,6 @@ Global
{4AF6A02D-82C8-4898-9EDF-01F107C25061}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AF6A02D-82C8-4898-9EDF-01F107C25061}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AF6A02D-82C8-4898-9EDF-01F107C25061}.Release|Any CPU.Build.0 = Release|Any CPU
- {8CA7C982-3EE4-4BCE-9493-7A63556736D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {8CA7C982-3EE4-4BCE-9493-7A63556736D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {8CA7C982-3EE4-4BCE-9493-7A63556736D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {8CA7C982-3EE4-4BCE-9493-7A63556736D3}.Release|Any CPU.Build.0 = Release|Any CPU
{4588351F-4233-4957-B84C-7F8E22B8888A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4588351F-4233-4957-B84C-7F8E22B8888A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4588351F-4233-4957-B84C-7F8E22B8888A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -55,20 +83,53 @@ Global
{DB954E01-898A-4FE2-A3AA-180D041AB08F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB954E01-898A-4FE2-A3AA-180D041AB08F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB954E01-898A-4FE2-A3AA-180D041AB08F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {04FC0651-B9D0-448A-A28B-11B1D4A897F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {04FC0651-B9D0-448A-A28B-11B1D4A897F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {04FC0651-B9D0-448A-A28B-11B1D4A897F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {04FC0651-B9D0-448A-A28B-11B1D4A897F4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {683A7D28-CC55-4375-848D-E659075ECEE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {683A7D28-CC55-4375-848D-E659075ECEE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {683A7D28-CC55-4375-848D-E659075ECEE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {683A7D28-CC55-4375-848D-E659075ECEE4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1CBEAEA8-2CA1-4B07-9930-35A785205852}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1CBEAEA8-2CA1-4B07-9930-35A785205852}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1CBEAEA8-2CA1-4B07-9930-35A785205852}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1CBEAEA8-2CA1-4B07-9930-35A785205852}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BA7828B1-7953-47A0-AE5A-E22B501C4BD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BA7828B1-7953-47A0-AE5A-E22B501C4BD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BA7828B1-7953-47A0-AE5A-E22B501C4BD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BA7828B1-7953-47A0-AE5A-E22B501C4BD0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {57E57290-3A6A-43F8-8764-D4DC8151F89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {57E57290-3A6A-43F8-8764-D4DC8151F89C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {57E57290-3A6A-43F8-8764-D4DC8151F89C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {57E57290-3A6A-43F8-8764-D4DC8151F89C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9F20CEA1-2216-4432-BBBD-F01E05D17F23} = {DE94CA7D-BB10-4865-85A6-6B694631247F}
- {4AF6A02D-82C8-4898-9EDF-01F107C25061} = {DE94CA7D-BB10-4865-85A6-6B694631247F}
+ {D311ABE4-10A9-4BB1-89CE-6358C55501A8} = {6BC42E6D-848C-4533-B715-F116E7DB3610}
+ {1578185F-C4FA-4866-936B-E62AAEDD03B7} = {AB415F5A-75E5-4E03-8A92-15CEDEC4CD3A}
{21CB448A-3882-4337-B416-D1A3E0BCFFC5} = {6BC42E6D-848C-4533-B715-F116E7DB3610}
{848DD000-3D22-4A25-A9D9-05AFF857A116} = {AB415F5A-75E5-4E03-8A92-15CEDEC4CD3A}
- {8CA7C982-3EE4-4BCE-9493-7A63556736D3} = {083161E5-6049-4D84-9739-9D7797D7117D}
+ {4AF6A02D-82C8-4898-9EDF-01F107C25061} = {DE94CA7D-BB10-4865-85A6-6B694631247F}
{4588351F-4233-4957-B84C-7F8E22B8888A} = {083161E5-6049-4D84-9739-9D7797D7117D}
{DB954E01-898A-4FE2-A3AA-180D041AB08F} = {083161E5-6049-4D84-9739-9D7797D7117D}
+ {04FC0651-B9D0-448A-A28B-11B1D4A897F4} = {841A2FA4-A95F-4612-A8B9-AD2EF769BC71}
+ {683A7D28-CC55-4375-848D-E659075ECEE4} = {841A2FA4-A95F-4612-A8B9-AD2EF769BC71}
+ {1CBEAEA8-2CA1-4B07-9930-35A785205852} = {DF0561A1-3AB8-4B51-AFB4-392EE1DD6247}
+ {BA7828B1-7953-47A0-AE5A-E22B501C4BD0} = {DF0561A1-3AB8-4B51-AFB4-392EE1DD6247}
+ {57E57290-3A6A-43F8-8764-D4DC8151F89C} = {7AC4B2C7-A55C-4C4F-9B02-77F5CBFFF4AB}
+ {841A2FA4-A95F-4612-A8B9-AD2EF769BC71} = {F9C2AAB1-C7B0-4E43-BB18-4FB16F6E272B}
+ {DF0561A1-3AB8-4B51-AFB4-392EE1DD6247} = {F9C2AAB1-C7B0-4E43-BB18-4FB16F6E272B}
+ {7AC4B2C7-A55C-4C4F-9B02-77F5CBFFF4AB} = {F9C2AAB1-C7B0-4E43-BB18-4FB16F6E272B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {10A5F2C3-5230-4916-9D4D-BBDB94851037}
EndGlobalSection
-EndGlobal
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{683a7d28-cc55-4375-848d-e659075ecee4}*SharedItemsImports = 5
+ ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{ba7828b1-7953-47a0-ae5a-e22b501c4bd0}*SharedItemsImports = 5
+ EndGlobalSection
+EndGlobal
\ No newline at end of file
diff --git a/src/libraries/System.Numerics.Tensors/src/ReferenceAssemblyExclusions.txt b/src/libraries/System.Numerics.Tensors/src/ReferenceAssemblyExclusions.txt
new file mode 100644
index 0000000000000..a8f2d0192cfec
--- /dev/null
+++ b/src/libraries/System.Numerics.Tensors/src/ReferenceAssemblyExclusions.txt
@@ -0,0 +1,2 @@
+M:System.Numerics.Tensors.TensorPrimitives.ConvertToHalf(System.ReadOnlySpan{System.Single},System.Span{System.Half})
+M:System.Numerics.Tensors.TensorPrimitives.ConvertToSingle(System.ReadOnlySpan{System.Half},System.Span{System.Single})
\ No newline at end of file
diff --git a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx
index 45f0d8fa17893..86b9f4d82b1f6 100644
--- a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx
+++ b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx
@@ -126,4 +126,7 @@
Input span arguments must all have the same length.
-
\ No newline at end of file
+
+ The destination span may only overlap with an input span if the two spans start at the same memory location.
+
+
diff --git a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj
index be4a04702af5e..52c6cb65811e6 100644
--- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj
+++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj
@@ -9,6 +9,7 @@
Once this package has shipped a stable version, the following line
should be removed in order to re-enable validation. -->
true
+ ReferenceAssemblyExclusions.txt
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 d28d4bacafdb8..03db1abb7f858 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
@@ -1,953 +1,1097 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
namespace System.Numerics.Tensors
{
/// Performs primitive tensor operations over spans of memory.
public static partial class TensorPrimitives
{
- /// Computes the element-wise result of: + .
+ /// 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.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// 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.
+ ///
+ ///
+ public static void Abs(ReadOnlySpan x, Span destination) =>
+ InvokeSpanIntoSpan(x, destination);
+
+ /// 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].
- public static unsafe void Add(ReadOnlySpan x, ReadOnlySpan y, Span destination) =>
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] + [i].
+ ///
+ ///
+ /// 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, 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] + .
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] + .
+ ///
+ ///
+ /// 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: - .
- /// 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 ''.
- /// Destination is too short.
- /// This method effectively does [i] = [i] - [i].
- public static void Subtract(ReadOnlySpan x, ReadOnlySpan y, Span destination) =>
- InvokeSpanSpanIntoSpan(x, y, destination);
-
- /// Computes the element-wise result of: - .
- /// 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] - .
- public static void Subtract(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 ''.
- /// Destination is too short.
- /// This method effectively does [i] = [i] * .
- public static void Multiply(ReadOnlySpan x, ReadOnlySpan y, Span destination) =>
- InvokeSpanSpanIntoSpan(x, y, destination);
-
- /// Computes the element-wise result of: * .
- /// 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 and the length of .
/// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
///
- /// This method effectively does [i] = [i] * .
- /// This method corresponds to the scal method defined by BLAS1.
+ ///
+ /// This method effectively computes [i] = ([i] + [i]) * [i].
+ ///
+ ///
+ /// If any 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);
+ 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] / .
- public static void Divide(ReadOnlySpan x, ReadOnlySpan y, Span destination) =>
- InvokeSpanSpanIntoSpan(x, y, destination);
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = ([i] + [i]) * .
+ ///
+ ///
+ /// 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 .
/// Destination is too short.
- /// This method effectively does [i] = [i] / .
- public static void Divide(ReadOnlySpan x, float y, Span destination) =>
- InvokeSpanScalarIntoSpan(x, y, destination);
-
- /// Computes the element-wise result of: -.
- /// The tensor, represented as a span.
- /// The destination tensor, represented as a span.
- /// Destination is too short.
- /// This method effectively does [i] = -[i].
- public static void Negate(ReadOnlySpan x, Span destination) =>
- InvokeSpanIntoSpan(x, destination);
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = ([i] + ) * [i].
+ ///
+ ///
+ /// 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: MathF.Abs().
+ /// 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] = MathF.Abs([i]).
- public static void Abs(ReadOnlySpan x, Span destination) =>
- InvokeSpanIntoSpan(x, destination);
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Cosh([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
- /// Computes the element-wise result of: ( + ) * .
+ /// 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 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]) * [i].
- public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan multiplier, Span destination) =>
- InvokeSpanSpanSpanIntoSpan(x, y, multiplier, destination);
+ /// 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)
+ {
+ ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
+ }
+
+ if (x.Length != y.Length)
+ {
+ ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
+ }
+
+ return CosineSimilarityCore(x, y);
+ }
- /// Computes the element-wise result of: ( + ) * .
+ /// 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 third tensor, represented as a scalar.
- /// The destination tensor, represented as a span.
- /// Length of '' must be same as length of ''.
- /// Destination is too short.
- /// This method effectively does [i] = ([i] + [i]) * .
- public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, float multiplier, Span destination) =>
- InvokeSpanSpanScalarIntoSpan(x, y, multiplier, destination);
+ /// The Euclidean distance.
+ /// 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)
+ {
+ ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
+ }
- /// Computes the element-wise result of: ( + ) * .
- /// 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 ''.
- /// Destination is too short.
- /// This method effectively does [i] = ([i] + ) * [i].
- public static void AddMultiply(ReadOnlySpan x, float y, ReadOnlySpan multiplier, Span destination) =>
- InvokeSpanScalarSpanIntoSpan(x, y, multiplier, destination);
+ 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 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 .
/// Destination is too short.
- /// This method effectively does [i] = ([i] * [i]) + [i].
- public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan addend, Span destination) =>
- InvokeSpanSpanSpanIntoSpan(x, y, addend, destination);
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] / [i].
+ ///
+ ///
+ /// 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 span.
- /// The third 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 ''.
/// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
///
- /// This method effectively does [i] = ([i] * [i]) + .
- /// This method corresponds to the axpy method defined by BLAS1.
+ ///
+ /// This method effectively computes [i] = [i] / .
+ ///
+ ///
+ /// 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);
+ public static void Divide(ReadOnlySpan x, float y, Span destination) =>
+ InvokeSpanScalarIntoSpan(x, y, destination);
- /// Computes the element-wise result of: ( * ) + .
+ /// 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 third tensor, represented as a span.
- /// The destination tensor, represented as a span.
- /// Length of '' must be same as length of ''.
- /// Destination is too short.
- /// This method effectively does [i] = ([i] * ) + [i].
- public static void MultiplyAdd(ReadOnlySpan x, float y, ReadOnlySpan addend, Span destination) =>
- InvokeSpanScalarSpanIntoSpan(x, y, addend, destination);
+ /// The dot product.
+ /// 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) =>
+ 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]).
- public static void Exp(ReadOnlySpan x, Span destination)
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Exp([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
+
+ /// 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 int IndexOfMax(ReadOnlySpan x)
{
- if (x.Length > destination.Length)
+ if (x.IsEmpty)
{
- ThrowHelper.ThrowArgument_DestinationTooShort();
+ return -1;
}
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Exp(x[i]);
- }
+ return IndexOfMinMaxCore(x);
}
- /// Computes the element-wise result of: ln().
+ /// 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 destination tensor, represented as a span.
- /// Destination is too short.
- /// This method effectively does [i] = .Log([i]).
- public static void Log(ReadOnlySpan x, Span destination)
+ /// 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 int IndexOfMaxMagnitude(ReadOnlySpan x)
{
- if (x.Length > destination.Length)
+ if (x.IsEmpty)
{
- ThrowHelper.ThrowArgument_DestinationTooShort();
+ return -1;
}
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Log(x[i]);
- }
+ return IndexOfMinMaxCore(x);
}
- /// Computes the element-wise result of: log2().
+ /// Searches for the index of the smallest 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] = .Log2([i]).
- public static void Log2(ReadOnlySpan x, Span destination)
+ /// 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 int IndexOfMin(ReadOnlySpan x)
{
- if (x.Length > destination.Length)
+ if (x.IsEmpty)
{
- ThrowHelper.ThrowArgument_DestinationTooShort();
+ return -1;
}
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = Log2(x[i]);
- }
+ return IndexOfMinMaxCore(x);
}
- /// Computes the element-wise result of: cosh().
+ /// 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 destination tensor, represented as a span.
- /// Destination is too short.
- /// This method effectively does [i] = .Cosh([i]).
- public static void Cosh(ReadOnlySpan x, Span destination)
+ /// 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 int IndexOfMinMagnitude(ReadOnlySpan x)
{
- if (x.Length > destination.Length)
+ if (x.IsEmpty)
{
- ThrowHelper.ThrowArgument_DestinationTooShort();
+ return -1;
}
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Cosh(x[i]);
- }
+ return IndexOfMinMaxCore(x);
}
- /// Computes the element-wise result of: sinh().
+ /// 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] = .Sinh([i]).
- public static void Sinh(ReadOnlySpan x, Span destination)
- {
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
-
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Sinh(x[i]);
- }
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Log([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
- /// Computes the element-wise result of: tanh().
+ /// 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] = .Tanh([i]).
- public static void Tanh(ReadOnlySpan x, Span destination)
- {
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Log2([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Tanh(x[i]);
- }
- }
+ /// 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.
+ ///
+ ///
+ /// 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 cosine similarity between two non-zero vectors.
+ /// 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 cosine similarity between the two vectors.
- /// Length of '' must be same as length of ''.
- /// '' and '' must not be empty.
- public static float CosineSimilarity(ReadOnlySpan x, ReadOnlySpan y)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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);
- return CosineSimilarityCore(x, y);
- }
+ /// Searches for the single-precision floating-point number with the largest magnitude in the specified tensor.
+ /// The tensor, represented as a span.
+ /// 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);
- ///
- /// Compute the distance between two points in Euclidean space.
- ///
+ /// 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 Euclidean distance.
- /// Length of '' must be same as length of ''.
- /// '' and '' must not be empty.
- public static float Distance(ReadOnlySpan x, ReadOnlySpan y)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// This method effectively computes [i] = MathF.MaxMagnitude([i], [i]).
+ ///
+ ///
+ /// 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);
- return MathF.Sqrt(Aggregate(0f, x, y));
- }
+ /// 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.
+ ///
+ ///
+ /// 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);
- ///
- /// A mathematical operation that takes two vectors and returns a scalar.
- ///
+ /// 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 dot product.
- /// Length of '' must be same as length of ''.
- public static float Dot(ReadOnlySpan x, ReadOnlySpan y) // BLAS1: dot
- {
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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);
- return Aggregate(0f, x, y);
- }
+ /// Searches for the single-precision floating-point number with the smallest magnitude in the specified tensor.
+ /// The tensor, represented as a span.
+ /// 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);
- ///
- /// A mathematical operation that takes a vector and returns the L2 norm.
- ///
+ /// 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 L2 norm.
- public static float Norm(ReadOnlySpan x) // BLAS1: nrm2
- {
- return MathF.Sqrt(Aggregate(0f, x));
- }
+ /// The second tensor, represented as a span.
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// 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.
+ ///
+ ///
+ /// 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);
- ///
- /// A function that takes a collection of real numbers and returns a probability distribution.
- ///
+ /// Computes the element-wise product of single-precision floating-point numbers in the specified tensors.
/// The first tensor, represented as a span.
- /// The destination tensor.
+ /// The second tensor, represented as a span.
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
/// Destination is too short.
- /// '' must not be empty.
- public static void SoftMax(ReadOnlySpan x, Span destination)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
-
- float expSum = 0f;
-
- for (int i = 0; i < x.Length; i++)
- {
- expSum += MathF.Exp(x[i]);
- }
-
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Exp(x[i]) / expSum;
- }
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] * [i].
+ ///
+ ///
+ /// 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);
- ///
- /// A function that takes a real number and returns a value between 0 and 1.
- ///
+ /// Computes the element-wise product of single-precision floating-point numbers in the specified tensors.
/// The first tensor, represented as a span.
- /// The destination tensor.
+ /// The second tensor, represented as a scalar.
+ /// The destination tensor, represented as a span.
/// Destination is too short.
- /// '' must not be empty.
- public static void Sigmoid(ReadOnlySpan x, Span destination)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
-
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = 1f / (1 + MathF.Exp(-x[i]));
- }
- }
-
- /// Computes the maximum element in .
- /// The tensor, represented as a span.
- /// The maximum element in .
- /// Length of '' must be greater than zero.
- public static float Max(ReadOnlySpan x)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
-
- float result = float.NegativeInfinity;
-
- 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 != result)
- {
- if (float.IsNaN(current))
- {
- return current;
- }
-
- if (result < current)
- {
- result = current;
- }
- }
- else if (IsNegative(result))
- {
- result = current;
- }
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] * .
+ /// It corresponds to the scal method defined by BLAS1.
+ ///
+ ///
+ /// 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);
- return result;
- }
+ /// 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 and length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = ([i] * [i]) + [i].
+ ///
+ ///
+ /// 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: MathF.Max(, ).
+ /// 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 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] = MathF.Max([i], [i]).
- public static void Max(ReadOnlySpan x, ReadOnlySpan y, Span destination)
- {
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = ([i] * [i]) + .
+ /// It corresponds to the axpy method defined by BLAS1.
+ ///
+ ///
+ /// 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);
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
+ /// 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 scalar.
+ /// The third tensor, represented as a span.
+ /// The destination tensor, represented as a span.
+ /// Length of must be same as length of .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = ([i] * ) + [i].
+ ///
+ ///
+ /// 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);
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Max(x[i], y[i]);
- }
- }
+ /// 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.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = -[i].
+ ///
+ ///
+ /// 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);
+
+ /// Computes the Euclidean norm of the specified tensor of single-precision floating-point numbers.
+ /// The first tensor, represented as a span.
+ /// 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 minimum element 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 minimum element in .
- /// Length of '' must be greater than zero.
- public static float Min(ReadOnlySpan x)
+ /// The result of multiplying all elements in .
+ /// 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)
{
ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
}
- float result = float.PositiveInfinity;
-
- 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 != result)
- {
- if (float.IsNaN(current))
- {
- return current;
- }
-
- if (current < result)
- {
- result = current;
- }
- }
- else if (IsNegative(current))
- {
- result = current;
- }
- }
-
- return result;
+ return Aggregate(x);
}
- /// Computes the element-wise result of: MathF.Min(, ).
+ /// 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 destination tensor, represented as a span.
- /// Length of '' must be same as length of ''.
- /// Destination is too short.
- /// This method effectively does [i] = MathF.Min([i], [i]).
- public static void Min(ReadOnlySpan x, ReadOnlySpan y, Span destination)
- {
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
-
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
-
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MathF.Min(x[i], y[i]);
- }
- }
-
- /// Computes the maximum magnitude of any element in .
- /// The tensor, represented as a span.
- /// The maximum magnitude of any element in .
- /// Length of '' must be greater than zero.
- public static float MaxMagnitude(ReadOnlySpan x)
+ /// 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 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)
{
ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
}
- float result = float.NegativeInfinity;
- float resultMag = float.NegativeInfinity;
-
- 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);
-
- if (currentMag != resultMag)
- {
- if (float.IsNaN(currentMag))
- {
- return currentMag;
- }
-
- if (resultMag < currentMag)
- {
- result = current;
- resultMag = currentMag;
- }
- }
- else if (IsNegative(result))
- {
- result = current;
- resultMag = currentMag;
- }
- }
-
- return result;
+ return Aggregate(x, y);
}
- /// Computes the element-wise result of: MathF.MaxMagnitude(, ).
+ /// 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 destination tensor, represented as a span.
- /// Length of '' must be same as length of ''.
- /// Destination is too short.
- /// This method effectively does [i] = MathF.MaxMagnitude([i], [i]).
- public static void MaxMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination)
+ /// 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 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.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
-
- if (x.Length > destination.Length)
+ if (x.IsEmpty)
{
- ThrowHelper.ThrowArgument_DestinationTooShort();
+ ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
}
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MaxMagnitude(x[i], y[i]);
- }
+ return Aggregate(x, y);
}
- /// Computes the minimum magnitude of any element in .
+ /// 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 minimum magnitude of any element in .
- /// Length of '' must be greater than zero.
- public static float MinMagnitude(ReadOnlySpan x)
+ /// The destination tensor.
+ /// Destination is too short.
+ /// must not be empty.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = 1f / (1f + .Exp(-[i])).
+ ///
+ ///
+ /// 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)
{
ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
}
- float result = float.PositiveInfinity;
- float resultMag = float.PositiveInfinity;
-
- 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);
-
- if (currentMag != resultMag)
- {
- if (float.IsNaN(currentMag))
- {
- return currentMag;
- }
-
- if (currentMag < resultMag)
- {
- result = current;
- resultMag = currentMag;
- }
- }
- else if (IsNegative(current))
- {
- result = current;
- resultMag = currentMag;
- }
- }
-
- return result;
+ InvokeSpanIntoSpan(x, destination);
}
- /// Computes the element-wise result of: MathF.MinMagnitude(, ).
- /// The first tensor, represented as a span.
- /// The second tensor, represented as a span.
+ /// 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.
- /// Length of '' must be same as length of ''.
/// Destination is too short.
- /// This method effectively does [i] = MathF.MinMagnitude([i], [i]).
- public static void MinMagnitude(ReadOnlySpan x, ReadOnlySpan y, Span destination)
- {
- if (x.Length != y.Length)
- {
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
- }
-
- if (x.Length > destination.Length)
- {
- ThrowHelper.ThrowArgument_DestinationTooShort();
- }
-
- for (int i = 0; i < x.Length; i++)
- {
- destination[i] = MinMagnitude(x[i], y[i]);
- }
- }
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Sinh([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
- /// Computes the index of the maximum element in .
+ /// Computes the softmax function over the specified non-empty tensor of single-precision floating-point numbers.
/// The tensor, represented as a span.
- /// The index of the maximum element in , or -1 if is empty.
- public static unsafe int IndexOfMax(ReadOnlySpan x)
+ /// The destination tensor.
+ /// Destination is too short.
+ /// must not be empty.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes a sum of MathF.Exp(x[i]) for all elements in .
+ /// It then effectively computes [i] = MathF.Exp([i]) / sum.
+ ///
+ ///
+ /// 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)
{
- int result = -1;
-
- if (!x.IsEmpty)
+ if (x.IsEmpty)
{
- float max = float.NegativeInfinity;
-
- 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)
- {
- if (float.IsNaN(current))
- {
- return i;
- }
-
- if (max < current)
- {
- result = i;
- max = current;
- }
- }
- else if (IsNegative(max) && !IsNegative(current))
- {
- result = i;
- max = current;
- }
- }
+ ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
}
- return result;
- }
-
- /// Computes the index of the minimum element in .
- /// The tensor, represented as a span.
- /// The index of the minimum element in , or -1 if is empty.
- public static unsafe int IndexOfMin(ReadOnlySpan x)
- {
- int result = -1;
-
- if (!x.IsEmpty)
+ if (x.Length > destination.Length)
{
- float min = float.PositiveInfinity;
-
- 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)
- {
- if (float.IsNaN(current))
- {
- return i;
- }
-
- if (current < min)
- {
- result = i;
- min = current;
- }
- }
- else if (IsNegative(current) && !IsNegative(min))
- {
- result = i;
- min = current;
- }
- }
+ ThrowHelper.ThrowArgument_DestinationTooShort();
}
- return result;
- }
+ ValidateInputOutputSpanNonOverlapping(x, destination);
- /// Computes the index of the element in with the maximum magnitude.
- /// 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.
- public static unsafe int IndexOfMaxMagnitude(ReadOnlySpan x)
- {
- int result = -1;
-
- if (!x.IsEmpty)
- {
- float max = float.NegativeInfinity;
- float maxMag = float.NegativeInfinity;
-
- 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);
-
- if (currentMag != maxMag)
- {
- if (float.IsNaN(currentMag))
- {
- return i;
- }
-
- if (maxMag < currentMag)
- {
- result = i;
- max = current;
- maxMag = currentMag;
- }
- }
- else if (IsNegative(max) && !IsNegative(current))
- {
- result = i;
- max = current;
- maxMag = currentMag;
- }
- }
- }
+ float expSum = Aggregate(x);
- return result;
+ InvokeSpanScalarIntoSpan(x, expSum, destination);
}
- /// Computes the index of the element in with the minimum magnitude.
- /// The tensor, represented as a span.
- /// The index of the element with the minimum magnitude, or -1 if is empty.
- public static unsafe int IndexOfMinMagnitude(ReadOnlySpan x)
- {
- int result = -1;
-
- if (!x.IsEmpty)
- {
- float min = float.PositiveInfinity;
- float minMag = float.PositiveInfinity;
-
- 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);
-
- if (currentMag != minMag)
- {
- if (float.IsNaN(currentMag))
- {
- return i;
- }
-
- if (currentMag < minMag)
- {
- result = i;
- min = current;
- minMag = currentMag;
- }
- }
- else if (IsNegative(current) && !IsNegative(min))
- {
- result = i;
- min = current;
- minMag = currentMag;
- }
- }
- }
+ /// 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 .
+ /// Destination is too short.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] - [i].
+ ///
+ ///
+ /// 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);
- return result;
- }
+ /// 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.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = [i] - .
+ ///
+ ///
+ /// 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(0f, x);
-
- /// Computes the sum of the squares of every element in .
- /// 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(, )).
- public static float SumOfSquares(ReadOnlySpan x) =>
- Aggregate(0f, 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(0f, x);
+ Aggregate(x);
- /// Computes the product of all elements 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 multiplying all elements in .
- /// Length of '' must be greater than zero.
- public static float Product(ReadOnlySpan x)
- {
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
+ /// 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);
- return Aggregate(1.0f, x);
- }
+ /// 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.
+ /// and reference overlapping memory locations and do not begin at the same location.
+ ///
+ ///
+ /// This method effectively computes [i] = .Tanh([i]).
+ ///
+ ///
+ /// 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) =>
+ InvokeSpanIntoSpan(x, destination);
- /// Computes the product of the element-wise result of: + .
- /// 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(, )).
- public static float ProductOfSums(ReadOnlySpan x, ReadOnlySpan y)
+ /// Throws an exception if the and spans overlap and don't begin at the same memory location.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void ValidateInputOutputSpanNonOverlapping(ReadOnlySpan input, Span output)
{
- if (x.IsEmpty)
- {
- ThrowHelper.ThrowArgument_SpansMustBeNonEmpty();
- }
-
- if (x.Length != y.Length)
+ if (!Unsafe.AreSame(ref MemoryMarshal.GetReference(input), ref MemoryMarshal.GetReference(output)) &&
+ input.Overlaps(output))
{
- ThrowHelper.ThrowArgument_SpansMustHaveSameLength();
+ ThrowHelper.ThrowArgument_InputAndDestinationSpanMustNotOverlap();
}
-
- return Aggregate(1.0f, x, y);
}
- ///