diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs index 7897a41ee6ce23..9dbd3503d137a6 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs @@ -159,197 +159,240 @@ public ref partial struct Enumerator } public static partial class Tensor { - public static System.Numerics.Tensors.Tensor AbsInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.Tensor Abs(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.Tensor AcoshInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Acosh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AcosInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AcosPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AcosPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Acos(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AddInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.Tensor AddInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.Tensor AsinhInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Asinh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AsinInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AsinPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AsinPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Asin(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Atan2InPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor Atan2PiInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor Atan2Pi(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor Atan2(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor AtanhInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Atanh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AtanInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AtanPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor AtanPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Atan(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor BitwiseAndInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor BitwiseAnd(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor BitwiseOrInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor BitwiseOr(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor Broadcast(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor Broadcast(System.Numerics.Tensors.Tensor input, System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor CeilingInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Ceiling(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Concatenate(System.ReadOnlySpan> tensors, int axis = 0) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Abs(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.INumberBase { throw null; } + public static System.Numerics.Tensors.Tensor Abs(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumberBase { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Acosh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Acosh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan AcosPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor AcosPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Acos(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Acos(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Add(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Add(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, T val, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Add(System.Numerics.Tensors.Tensor input, T val) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Asinh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Asinh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan AsinPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor AsinPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Asin(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Asin(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.ReadOnlyTensorSpan AsReadOnlyTensorSpan(this T[]? array, params scoped System.ReadOnlySpan shape) { throw null; } + public static System.Numerics.Tensors.TensorSpan AsTensorSpan(this T[]? array, params scoped System.ReadOnlySpan shape) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Atan2Pi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static System.Numerics.Tensors.Tensor Atan2Pi(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Atan2(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static System.Numerics.Tensors.Tensor Atan2(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Atanh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Atanh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan AtanPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor AtanPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Atan(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Atan(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan BitwiseAnd(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBitwiseOperators { throw null; } + public static System.Numerics.Tensors.Tensor BitwiseAnd(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IBitwiseOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan BitwiseOr(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBitwiseOperators { throw null; } + public static System.Numerics.Tensors.Tensor BitwiseOr(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IBitwiseOperators { throw null; } + public static void BroadcastTo(this in System.Numerics.Tensors.ReadOnlyTensorSpan source, in System.Numerics.Tensors.TensorSpan destination) { } + public static void BroadcastTo(this in System.Numerics.Tensors.TensorSpan source, in System.Numerics.Tensors.TensorSpan destination) { } + public static void BroadcastTo(this System.Numerics.Tensors.Tensor source, in System.Numerics.Tensors.TensorSpan destination) { } + public static System.Numerics.Tensors.Tensor Broadcast(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan lengthsSource) { throw null; } + public static System.Numerics.Tensors.Tensor Broadcast(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, scoped System.ReadOnlySpan lengths) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Cbrt(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Cbrt(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IRootFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Ceiling(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Ceiling(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Concatenate(scoped System.ReadOnlySpan> tensors, int axis = 0) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ConvertChecked(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan source, in System.Numerics.Tensors.TensorSpan destination) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } public static System.Numerics.Tensors.Tensor ConvertChecked(System.Numerics.Tensors.Tensor source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ConvertSaturating(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan source, in System.Numerics.Tensors.TensorSpan destination) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } public static System.Numerics.Tensors.Tensor ConvertSaturating(System.Numerics.Tensors.Tensor source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ConvertTruncating(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan source, in System.Numerics.Tensors.TensorSpan destination) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } public static System.Numerics.Tensors.Tensor ConvertTruncating(System.Numerics.Tensors.Tensor source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.Tensor CopySignInPlace(System.Numerics.Tensors.Tensor input, System.Numerics.Tensors.Tensor sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor CopySignInPlace(System.Numerics.Tensors.Tensor input, T sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor CopySign(System.Numerics.Tensors.Tensor input, System.Numerics.Tensors.Tensor sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor CopySign(System.Numerics.Tensors.Tensor input, T sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor CoshInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Cosh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CosineSimilarity(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CosInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CosPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CosPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Cos(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CreateAndFillGaussianNormalDistribution(params scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor CreateAndFillUniformDistribution(params scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor CreateFromEnumerable(System.Collections.Generic.IEnumerable data) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned = false) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, bool pinned = false) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool isPinned = false) where T : System.IEquatable { throw null; } - public static System.Numerics.Tensors.Tensor CubeRootInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor CubeRoot(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor DegreesToRadiansInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor DegreesToRadians(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static T Distance(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor DivideInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.Tensor DivideInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.Tensor DivideInPlace(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Divide(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static T Dot(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } - public static System.Numerics.Tensors.Tensor Exp10InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp10M1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp10M1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp10(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp2InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp2M1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp2M1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp2(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor ExpInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor ExpM1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor ExpM1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Exp(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor FilteredUpdate(System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor filter, System.Numerics.Tensors.Tensor values) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor FilteredUpdate(System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor filter, T value) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor FloorInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Floor(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static bool GreaterThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static bool GreaterThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, T right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor HypotenuseInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Hypotenuse(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Ieee754RemainderInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor Ieee754Remainder(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.Tensor ILogB(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static int IndexOfMaxMagnitude(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMax(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMinMagnitude(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMin(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor LeadingZeroCountInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.Tensor LeadingZeroCount(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static bool LessThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static bool LessThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, T right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IComparisonOperators { throw null; } - public static System.Numerics.Tensors.Tensor Log10InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log10P1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log10P1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log10(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log2InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log2P1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log2P1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log2(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor LogInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor LogP1InPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor LogP1(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Log(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static T MaxMagnitude(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T MaxNumber(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Max(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Mean(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static TResult Mean(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static T MinMagnitude(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T MinNumber(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Min(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.Tensor MultiplyInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.Tensor MultiplyInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.Tensor NegateInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IUnaryNegationOperators { throw null; } - public static System.Numerics.Tensors.Tensor Negate(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IUnaryNegationOperators { throw null; } - public static T Norm(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor OnesComplementInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor OnesComplement(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor Permute(System.Numerics.Tensors.Tensor input, params scoped System.ReadOnlySpan axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor PopCountInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.Tensor PopCount(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.Tensor PowInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IPowerFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Pow(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IPowerFunctions { throw null; } - public static T Product(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } - public static System.Numerics.Tensors.Tensor RadiansToDegreesInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor RadiansToDegrees(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor ReciprocalInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Reciprocal(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Reshape(this System.Numerics.Tensors.Tensor input, params scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor Resize(System.Numerics.Tensors.Tensor input, System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor Reverse(System.Numerics.Tensors.Tensor input, nint axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor RoundInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Round(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor SequenceEqual(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor SetSlice(this System.Numerics.Tensors.Tensor tensor, System.Numerics.Tensors.Tensor values, params scoped System.ReadOnlySpan ranges) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor SigmoidInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Sigmoid(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SinhInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Sinh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SinInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SinPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SinPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Sin(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SoftMaxInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor SoftMax(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.Tensor[] Split(System.Numerics.Tensors.Tensor input, nint numSplits, nint axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor SqrtInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Sqrt(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Squeeze(System.Numerics.Tensors.Tensor input, int axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor Stack(System.Numerics.Tensors.Tensor[] input, int axis = 0) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static T StdDev(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static TResult StdDev(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber, System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor SubtractInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.Tensor SubtractInPlace(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.Tensor SubtractInPlace(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.Tensor Subtract(T val, System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static T Sum(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.Tensor TanhInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Tanh(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.Tensor TanInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor TanPiInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor TanPi(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor Tan(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.Tensor TrailingZeroCountInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.Tensor TrailingZeroCount(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.Tensor Transpose(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor TruncateInPlace(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Truncate(System.Numerics.Tensors.Tensor input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.Tensor Unsqueeze(System.Numerics.Tensors.Tensor input, int axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.Tensor XorInPlace(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.Tensor Xor(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan CopySign(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan sign, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.INumber { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan CopySign(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, T sign, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.INumber { throw null; } + public static System.Numerics.Tensors.Tensor CopySign(System.Numerics.Tensors.Tensor input, System.Numerics.Tensors.Tensor sign) where T : System.Numerics.INumber { throw null; } + public static System.Numerics.Tensors.Tensor CopySign(System.Numerics.Tensors.Tensor input, T sign) where T : System.Numerics.INumber { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Cosh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Cosh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan CosineSimilarity(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor CosineSimilarity(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IRootFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan CosPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor CosPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Cos(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Cos(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor CreateAndFillGaussianNormalDistribution(params scoped System.ReadOnlySpan lengths) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor CreateAndFillUniformDistribution(params scoped System.ReadOnlySpan lengths) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, bool pinned = false) { throw null; } + public static System.Numerics.Tensors.Tensor CreateUninitialized(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) { throw null; } + public static System.Numerics.Tensors.Tensor Create(System.Collections.Generic.IEnumerable data, scoped System.ReadOnlySpan lengths) { throw null; } + public static System.Numerics.Tensors.Tensor Create(System.Collections.Generic.IEnumerable data, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool isPinned = false) { throw null; } + public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, bool pinned = false) { throw null; } + public static System.Numerics.Tensors.Tensor Create(scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool pinned = false) { throw null; } + public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths) { throw null; } + public static System.Numerics.Tensors.Tensor Create(T[] values, scoped System.ReadOnlySpan lengths, scoped System.ReadOnlySpan strides, bool isPinned = false) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan DegreesToRadians(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor DegreesToRadians(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static T Distance(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right) where T : System.Numerics.IRootFunctions { throw null; } + public static T Distance(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IRootFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Divide(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IDivisionOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Divide(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, T val, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(System.Numerics.Tensors.Tensor input, T val) where T : System.Numerics.IDivisionOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Divide(T val, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IDivisionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Divide(T val, System.Numerics.Tensors.Tensor input) where T : System.Numerics.IDivisionOperators { throw null; } + public static T Dot(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } + public static T Dot(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ElementwiseEqual(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IEqualityOperators { throw null; } + public static System.Numerics.Tensors.Tensor ElementwiseEqual(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IEqualityOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Exp10M1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Exp10M1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Exp10(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Exp10(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Exp2M1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Exp2M1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Exp2(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Exp2(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ExpM1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor ExpM1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Exp(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Exp(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan FillGaussianNormalDistribution(in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan FillUniformDistribution(in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.TensorSpan FilteredUpdate(this in System.Numerics.Tensors.TensorSpan tensor, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan filter, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan values) { throw null; } + public static System.Numerics.Tensors.TensorSpan FilteredUpdate(this in System.Numerics.Tensors.TensorSpan tensor, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan filter, T value) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Floor(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Floor(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPoint { throw null; } + public static nint[] GetSmallestBroadcastableLengths(System.ReadOnlySpan shape1, System.ReadOnlySpan shape2) { throw null; } + public static bool GreaterThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static bool GreaterThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor GreaterThan(System.Numerics.Tensors.Tensor left, T right) where T : System.Numerics.IComparisonOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Hypot(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Hypot(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IRootFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Ieee754Remainder(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static System.Numerics.Tensors.Tensor Ieee754Remainder(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan ILogB(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static System.Numerics.Tensors.Tensor ILogB(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPointIeee754 { throw null; } + public static int IndexOfMaxMagnitude(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMaxMagnitude(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMax(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMax(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMinMagnitude(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMinMagnitude(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMin(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static int IndexOfMin(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan LeadingZeroCount(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBinaryInteger { throw null; } + public static System.Numerics.Tensors.Tensor LeadingZeroCount(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IBinaryInteger { throw null; } + public static bool LessThanAll(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static bool LessThanAny(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IComparisonOperators { throw null; } + public static System.Numerics.Tensors.Tensor LessThan(System.Numerics.Tensors.Tensor left, T right) where T : System.Numerics.IComparisonOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Log10P1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log10P1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Log10(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log10(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Log2P1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log2P1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Log2(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log2(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan LogP1(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor LogP1(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Log(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Log(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ILogarithmicFunctions { throw null; } + public static T MaxMagnitude(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T MaxMagnitude(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static T MaxNumber(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T MaxNumber(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static T Max(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T Max(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static T Mean(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.IFloatingPoint { throw null; } + public static T MinMagnitude(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T MinMagnitude(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static T MinNumber(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T MinNumber(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static T Min(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.INumber { throw null; } + public static T Min(System.Numerics.Tensors.Tensor input) where T : System.Numerics.INumber { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Multiply(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Multiply(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, T val, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static System.Numerics.Tensors.Tensor Multiply(System.Numerics.Tensors.Tensor input, T val) where T : System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Negate(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IUnaryNegationOperators { throw null; } + public static System.Numerics.Tensors.Tensor Negate(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IUnaryNegationOperators { throw null; } + public static T Norm(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.IRootFunctions { throw null; } + public static T Norm(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IRootFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan OnesComplement(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBitwiseOperators { throw null; } + public static System.Numerics.Tensors.Tensor OnesComplement(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IBitwiseOperators { throw null; } + public static System.Numerics.Tensors.Tensor Permute(this System.Numerics.Tensors.Tensor input, params scoped System.ReadOnlySpan axis) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan PopCount(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBinaryInteger { throw null; } + public static System.Numerics.Tensors.Tensor PopCount(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IBinaryInteger { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Pow(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IPowerFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Pow(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IPowerFunctions { throw null; } + public static T Product(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } + public static T Product(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan RadiansToDegrees(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor RadiansToDegrees(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Reciprocal(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Reciprocal(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.ReadOnlyTensorSpan Reshape(this in System.Numerics.Tensors.ReadOnlyTensorSpan input, params scoped System.ReadOnlySpan lengths) { throw null; } + public static System.Numerics.Tensors.TensorSpan Reshape(this in System.Numerics.Tensors.TensorSpan input, params scoped System.ReadOnlySpan lengths) { throw null; } + public static System.Numerics.Tensors.Tensor Reshape(this System.Numerics.Tensors.Tensor input, params scoped System.ReadOnlySpan lengths) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Resize(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) { throw null; } + public static System.Numerics.Tensors.Tensor Resize(System.Numerics.Tensors.Tensor input, System.ReadOnlySpan shape) { throw null; } + public static System.Numerics.Tensors.Tensor Reverse(in System.Numerics.Tensors.ReadOnlyTensorSpan input, nint axis = -1) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Reverse(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination, nint axis = -1) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Round(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Round(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPoint { throw null; } + public static bool SequenceEqual(this scoped in System.Numerics.Tensors.ReadOnlyTensorSpan span, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan other) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan SetSlice(this in System.Numerics.Tensors.TensorSpan tensor, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan values, params scoped System.ReadOnlySpan ranges) { throw null; } + public static System.Numerics.Tensors.Tensor SetSlice(this System.Numerics.Tensors.Tensor tensor, in System.Numerics.Tensors.ReadOnlyTensorSpan values, params scoped System.ReadOnlySpan ranges) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Sigmoid(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sigmoid(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Sinh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sinh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan SinPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor SinPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Sin(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sin(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan SoftMax(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor SoftMax(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IExponentialFunctions { throw null; } + public static System.Numerics.Tensors.Tensor[] Split(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, nint numSplits, nint axis) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Sqrt(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Sqrt(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IRootFunctions { throw null; } + public static System.Numerics.Tensors.ReadOnlyTensorSpan Squeeze(this in System.Numerics.Tensors.ReadOnlyTensorSpan input, int axis = -1) { throw null; } + public static System.Numerics.Tensors.TensorSpan Squeeze(this in System.Numerics.Tensors.TensorSpan input, int axis = -1) { throw null; } + public static System.Numerics.Tensors.Tensor Squeeze(this System.Numerics.Tensors.Tensor input, int axis = -1) { throw null; } + public static System.Numerics.Tensors.Tensor Stack(System.ReadOnlySpan> input, int axis = 0) { throw null; } + public static T StdDev(in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Subtract(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ISubtractionOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Subtract(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, T val, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(System.Numerics.Tensors.Tensor input, T val) where T : System.Numerics.ISubtractionOperators { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Subtract(T val, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ISubtractionOperators { throw null; } + public static System.Numerics.Tensors.Tensor Subtract(T val, System.Numerics.Tensors.Tensor input) where T : System.Numerics.ISubtractionOperators { throw null; } + public static T Sum(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static T Sum(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Tanh(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Tanh(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IHyperbolicFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan TanPi(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor TanPi(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Tan(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static System.Numerics.Tensors.Tensor Tan(System.Numerics.Tensors.Tensor input) where T : System.Numerics.ITrigonometricFunctions { throw null; } + public static string ToString(this in System.Numerics.Tensors.ReadOnlyTensorSpan span, params scoped System.ReadOnlySpan maximumLengths) { throw null; } + public static string ToString(this in System.Numerics.Tensors.TensorSpan span, params scoped System.ReadOnlySpan maximumLengths) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan TrailingZeroCount(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBinaryInteger { throw null; } + public static System.Numerics.Tensors.Tensor TrailingZeroCount(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IBinaryInteger { throw null; } + public static System.Numerics.Tensors.Tensor Transpose(System.Numerics.Tensors.Tensor input) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Truncate(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IFloatingPoint { throw null; } + public static System.Numerics.Tensors.Tensor Truncate(System.Numerics.Tensors.Tensor input) where T : System.Numerics.IFloatingPoint { throw null; } + public static bool TryBroadcastTo(this in System.Numerics.Tensors.ReadOnlyTensorSpan input, in System.Numerics.Tensors.TensorSpan destination) { throw null; } + public static bool TryBroadcastTo(this in System.Numerics.Tensors.TensorSpan input, in System.Numerics.Tensors.TensorSpan destination) { throw null; } + public static bool TryBroadcastTo(this System.Numerics.Tensors.Tensor input, in System.Numerics.Tensors.TensorSpan destination) { throw null; } + public static System.Numerics.Tensors.ReadOnlyTensorSpan Unsqueeze(this in System.Numerics.Tensors.ReadOnlyTensorSpan input, int axis) { throw null; } + public static System.Numerics.Tensors.TensorSpan Unsqueeze(this in System.Numerics.Tensors.TensorSpan input, int axis) { throw null; } + public static System.Numerics.Tensors.Tensor Unsqueeze(this System.Numerics.Tensors.Tensor input, int axis) { throw null; } + public static ref readonly System.Numerics.Tensors.TensorSpan Xor(scoped in System.Numerics.Tensors.ReadOnlyTensorSpan left, scoped in System.Numerics.Tensors.ReadOnlyTensorSpan right, in System.Numerics.Tensors.TensorSpan destination) where T : System.Numerics.IBitwiseOperators { throw null; } + public static System.Numerics.Tensors.Tensor Xor(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) where T : System.Numerics.IBitwiseOperators { throw null; } } public static partial class TensorPrimitives { @@ -502,180 +545,6 @@ public static void Truncate(System.ReadOnlySpan x, System.Span destinat public static void Xor(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) where T : System.Numerics.IBitwiseOperators { } public static void Xor(System.ReadOnlySpan x, T y, System.Span destination) where T : System.Numerics.IBitwiseOperators { } } - public static partial class TensorSpan - { - public static System.Numerics.Tensors.TensorSpan AbsInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.TensorSpan Abs(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.TensorSpan AcoshInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Acosh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AcosInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AcosPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AcosPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Acos(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AddInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan AddInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan Add(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan Add(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan AsinhInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Asinh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AsinInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AsinPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AsinPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Asin(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AsTensorSpan(this T[]? array, params scoped System.ReadOnlySpan shape) { throw null; } - public static System.Numerics.Tensors.TensorSpan Atan2InPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan Atan2PiInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan Atan2Pi(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan Atan2(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan AtanhInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Atanh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AtanInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AtanPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan AtanPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Atan(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan BitwiseAndInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan BitwiseAnd(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan BitwiseOrInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan BitwiseOr(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Broadcast(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Broadcast(System.Numerics.Tensors.TensorSpan input, System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan CeilingInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Ceiling(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan ConvertChecked(System.Numerics.Tensors.TensorSpan source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.TensorSpan ConvertSaturating(System.Numerics.Tensors.TensorSpan source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.TensorSpan ConvertTruncating(System.Numerics.Tensors.TensorSpan source) where TFrom : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumberBase where TTo : System.Numerics.INumberBase { throw null; } - public static System.Numerics.Tensors.TensorSpan CopySignInPlace(System.Numerics.Tensors.TensorSpan input, System.Numerics.Tensors.TensorSpan sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan CopySignInPlace(System.Numerics.Tensors.TensorSpan input, T sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan CopySign(System.Numerics.Tensors.TensorSpan input, System.Numerics.Tensors.TensorSpan sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan CopySign(System.Numerics.Tensors.TensorSpan input, T sign) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan CoshInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Cosh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CosineSimilarity(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CosInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CosPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CosPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Cos(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CubeRootInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan CubeRoot(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan DegreesToRadiansInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan DegreesToRadians(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static T Distance(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan DivideInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan DivideInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan DivideInPlace(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Divide(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Divide(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Divide(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IDivisionOperators { throw null; } - public static T Dot(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp10InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp10M1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp10M1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp10(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp2InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp2M1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp2M1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp2(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan ExpInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan ExpM1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan ExpM1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Exp(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan FloorInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Floor(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan HypotenuseInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Hypotenuse(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Ieee754RemainderInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan Ieee754Remainder(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static System.Numerics.Tensors.TensorSpan ILogB(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointIeee754 { throw null; } - public static int IndexOfMaxMagnitude(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMax(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMinMagnitude(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static int IndexOfMin(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan LeadingZeroCountInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan LeadingZeroCount(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan Log10InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log10P1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log10P1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log10(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log2InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log2P1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log2P1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log2(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan LogInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan LogP1InPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan LogP1(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Log(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ILogarithmicFunctions { throw null; } - public static T MaxMagnitude(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T MaxNumber(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Max(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Mean(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static TResult Mean(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static T MinMagnitude(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T MinNumber(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static T Min(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber { throw null; } - public static System.Numerics.Tensors.TensorSpan MultiplyInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan MultiplyInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan Multiply(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan Multiply(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplyOperators, System.Numerics.IMultiplicativeIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan NegateInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IUnaryNegationOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Negate(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IUnaryNegationOperators { throw null; } - public static T Norm(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan OnesComplementInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan OnesComplement(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan PopCountInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan PopCount(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan PowInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IPowerFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Pow(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IPowerFunctions { throw null; } - public static T Product(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan RadiansToDegreesInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan RadiansToDegrees(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan ReciprocalInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Reciprocal(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Reshape(this System.Numerics.Tensors.TensorSpan input, params scoped System.ReadOnlySpan lengths) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Resize(System.Numerics.Tensors.TensorSpan input, System.ReadOnlySpan shape) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Reverse(System.Numerics.Tensors.TensorSpan input, nint axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan RoundInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Round(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static bool SequenceEqual(this System.Numerics.Tensors.ReadOnlyTensorSpan span, in System.Numerics.Tensors.ReadOnlyTensorSpan other) where T : System.IEquatable? { throw null; } - public static bool SequenceEqual(this System.Numerics.Tensors.TensorSpan span, in System.Numerics.Tensors.ReadOnlyTensorSpan other) where T : System.IEquatable? { throw null; } - public static bool SequenceEqual(this System.Numerics.Tensors.TensorSpan span, in System.Numerics.Tensors.TensorSpan other) where T : System.IEquatable? { throw null; } - public static System.Numerics.Tensors.TensorSpan SigmoidInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Sigmoid(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SinhInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Sinh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SinInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SinPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SinPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Sin(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SoftMaxInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SoftMax(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan SqrtInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Sqrt(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IRootFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Squeeze(System.Numerics.Tensors.TensorSpan input, int axis = -1) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static T StdDev(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static TResult StdDev(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.INumber, System.Numerics.IFloatingPoint, System.Numerics.IPowerFunctions, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity where TResult : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan SubtractInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan SubtractInPlace(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan SubtractInPlace(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Subtract(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Subtract(System.Numerics.Tensors.TensorSpan input, T val) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Subtract(T val, System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ISubtractionOperators { throw null; } - public static T Sum(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity { throw null; } - public static System.Numerics.Tensors.TensorSpan TanhInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Tanh(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IHyperbolicFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan TanInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan TanPiInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan TanPi(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static System.Numerics.Tensors.TensorSpan Tan(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.ITrigonometricFunctions { throw null; } - public static string ToString(this System.Numerics.Tensors.ReadOnlyTensorSpan span, params scoped System.ReadOnlySpan maximumLengths) { throw null; } - public static string ToString(this System.Numerics.Tensors.TensorSpan span, params scoped System.ReadOnlySpan maximumLengths) { throw null; } - public static System.Numerics.Tensors.TensorSpan TrailingZeroCountInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan TrailingZeroCount(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBinaryInteger { throw null; } - public static System.Numerics.Tensors.TensorSpan TruncateInPlace(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Truncate(System.Numerics.Tensors.TensorSpan input) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint { throw null; } - public static System.Numerics.Tensors.TensorSpan Unsqueeze(System.Numerics.Tensors.TensorSpan input, int axis) where T : System.IEquatable, System.Numerics.IEqualityOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan XorInPlace(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - public static System.Numerics.Tensors.TensorSpan Xor(System.Numerics.Tensors.TensorSpan left, System.Numerics.Tensors.TensorSpan right) where T : System.IEquatable, System.Numerics.IEqualityOperators, System.Numerics.IBitwiseOperators { throw null; } - } public readonly ref partial struct TensorSpan { private readonly object _dummy; diff --git a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx index 505dc853fcd16f..7fc5ad881af0cd 100644 --- a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx +++ b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx @@ -225,4 +225,7 @@ Incompatible dimensions for provided tensors. left.Lengths[1] == {0} while right.Lengths[1] == {1}. - \ No newline at end of file + + All tensors must have the same shape. + + 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 0044dbdd1a4cf2..c36d7356debfb1 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -23,7 +23,6 @@ - diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs index bad5e28d41ecf9..a823f92e37b8e6 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs @@ -775,7 +775,14 @@ public void FlattenTo(scoped Span destination) nint copiedValues = 0; while (copiedValues < _flattenedLength) { - TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + if (Strides[Rank - 1] == 0) + { + destination.Slice(checked((int)copiedValues), (int)Lengths[Rank - 1]).Fill(Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths))); + } + else + { + TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]); + } TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths); copiedValues += Lengths[Rank - 1]; } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs index 0bd2f2986cebaa..7c3309d6ad65d6 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.Factory.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using Microsoft.VisualBasic; #pragma warning disable CS8601 // Possible null reference assignment. @@ -19,7 +20,6 @@ public static partial class Tensor /// A indicating the lengths of each dimension. /// A whether the underlying data should be pinned or not. public static Tensor Create(scoped ReadOnlySpan lengths, bool pinned = false) - where T : IEquatable { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); @@ -33,7 +33,6 @@ public static Tensor Create(scoped ReadOnlySpan lengths, bool pinned /// A indicating the strides of each dimension. /// A whether the underlying data should be pinned or not. public static Tensor Create(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false) - where T : IEquatable { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = pinned ? GC.AllocateArray((int)linearLength, pinned) : (new T[linearLength]); @@ -48,7 +47,7 @@ public static Tensor Create(scoped ReadOnlySpan lengths, scoped Read /// A indicating the lengths of each dimension. /// public static Tensor Create(T[] values, scoped ReadOnlySpan lengths) - where T : IEquatable => Create(values, lengths, []); + => Create(values, lengths, []); /// /// Creates a from the provided . If the product of the @@ -60,43 +59,32 @@ public static Tensor Create(T[] values, scoped ReadOnlySpan lengths) /// A indicating whether the were pinned or not. /// public static Tensor Create(T[] values, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool isPinned = false) - where T : IEquatable { return new Tensor(values, lengths, strides, isPinned); } /// - /// Creates a and does not initialize it. If is true, the memory will be pinned. - /// - /// A indicating the lengths of each dimension. - /// A whether the underlying data should be pinned or not. - public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, bool pinned = false) - where T : IEquatable => CreateUninitialized(lengths, [], pinned); - - - /// - /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// Creates a and initializes it with the data from . /// - /// A indicating the lengths of each dimension. - /// A indicating the strides of each dimension. - /// A whether the underlying data should be pinned or not. - public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false ) - where T : IEquatable + /// A with the data to use for the initialization. + /// + public static Tensor Create(IEnumerable data, scoped ReadOnlySpan lengths) { - nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); - T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); - return new Tensor(values, lengths, strides, pinned); + T[] values = data.ToArray(); + return new Tensor(values, lengths.IsEmpty ? [values.Length] : lengths, false); } /// /// Creates a and initializes it with the data from . /// /// A with the data to use for the initialization. - public static Tensor CreateFromEnumerable(IEnumerable data) - where T : IEquatable, IEqualityOperators + /// + /// + /// + public static Tensor Create(IEnumerable data, scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool isPinned = false) { T[] values = data.ToArray(); - return new Tensor(values, [values.Length], false); + return new Tensor(values, lengths.IsEmpty ? [values.Length] : lengths, strides, isPinned); } /// @@ -104,7 +92,7 @@ public static Tensor CreateFromEnumerable(IEnumerable data) /// /// A indicating the lengths of each dimension. public static Tensor CreateAndFillUniformDistribution(params scoped ReadOnlySpan lengths) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = new T[linearLength]; @@ -121,16 +109,16 @@ public static Tensor CreateAndFillUniformDistribution(params scoped ReadOn /// /// A indicating the lengths of each dimension. public static Tensor CreateAndFillGaussianNormalDistribution(params scoped ReadOnlySpan lengths) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); T[] values = new T[linearLength]; - GaussianDistribution(ref values, linearLength); + GaussianDistribution(values, linearLength); return new Tensor(values, lengths, false); } - private static void GaussianDistribution(ref T[] values, nint linearLength) - where T : IEquatable, IEqualityOperators, IFloatingPoint + private static void GaussianDistribution(in Span values, nint linearLength) + where T : IFloatingPoint { Random rand = Random.Shared; for (int i = 0; i < linearLength; i++) @@ -141,5 +129,45 @@ private static void GaussianDistribution(ref T[] values, nint linearLength) } } #endregion + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, bool pinned = false) + => CreateUninitialized(lengths, [], pinned); + + /// + /// Creates a and does not initialize it. If is true, the memory will be pinned. + /// + /// A indicating the lengths of each dimension. + /// A indicating the strides of each dimension. + /// A whether the underlying data should be pinned or not. + public static Tensor CreateUninitialized(scoped ReadOnlySpan lengths, scoped ReadOnlySpan strides, bool pinned = false) + { + nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths); + T[] values = GC.AllocateUninitializedArray((int)linearLength, pinned); + return new Tensor(values, lengths, strides, pinned); + } + + public static ref readonly TensorSpan FillGaussianNormalDistribution(in TensorSpan destination) where T : IFloatingPoint + { + Span span = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination._flattenedLength); + + GaussianDistribution(span, destination._flattenedLength); + + return ref destination; + } + + public static ref readonly TensorSpan FillUniformDistribution(in TensorSpan destination) where T : IFloatingPoint + { + Span span = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination._flattenedLength); + + for (int i = 0; i < span.Length; i++) + span[i] = T.CreateChecked(Random.Shared.NextDouble()); + + return ref destination; + } } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs index 4927b46eb658a8..94af59482b520c 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorExtensions.cs @@ -9,6 +9,8 @@ using System.Text; using System.Buffers; using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Security.Cryptography; +using System.Runtime.Serialization; #pragma warning disable CS8601 // Possible null reference assignment. #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. @@ -18,58 +20,100 @@ namespace System.Numerics.Tensors { public static partial class Tensor { - #region Resize + #region AsTensorSpan /// - /// Creates a new , allocates new memory, and copies the data from . If the final shape is smaller all data after - /// that point is ignored. + /// Extension method to more easily create a TensorSpan from an array. + /// + /// The type of the elements in the array + /// The with the data + /// The shape for the + /// + public static TensorSpan AsTensorSpan(this T[]? array, params scoped ReadOnlySpan shape) => new(array, 0, shape, default); + #endregion + + #region AsReadOnlySpan + /// + /// Extension method to more easily create a TensorSpan from an array. + /// + /// The type of the elements in the array + /// The with the data + /// The shape for the + /// + public static ReadOnlyTensorSpan AsReadOnlyTensorSpan(this T[]? array, params scoped ReadOnlySpan shape) => new(array, 0, shape, default); + #endregion + + #region Broadcast + /// + /// Broadcast the data from to the smallest broadcastable shape compatible with . Creates a new and allocates new memory. /// /// Input . - /// of the desired new shape. - public static Tensor Resize(Tensor input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators + /// Other to make shapes broadcastable. + public static Tensor Broadcast(scoped in ReadOnlyTensorSpan input, scoped in ReadOnlyTensorSpan lengthsSource) { - nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); - T[] values = input.IsPinned ? GC.AllocateArray((int)newSize) : (new T[newSize]); - Tensor output = new Tensor(values, shape, false); - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input.AsTensorSpan()._reference, (int)input.FlattenedLength); - Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); - if (newSize > input.FlattenedLength) - TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); - else - TensorSpanHelpers.Memmove(ospan, span, newSize); + return Broadcast(input, lengthsSource.Lengths); + } + /// + /// Broadcast the data from to the new shape . Creates a new and allocates new memory. + /// If the shape of the is not compatible with the new shape, an exception is thrown. + /// + /// Input . + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + public static Tensor Broadcast(scoped in ReadOnlyTensorSpan input, scoped ReadOnlySpan lengths) + { + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(input.Lengths, lengths); + + ReadOnlyTensorSpan intermediate = LazyBroadcast(input, newSize); + Tensor output = Tensor.CreateUninitialized(intermediate.Lengths); + intermediate.FlattenTo(MemoryMarshal.CreateSpan(ref output._values[0], (int)output.FlattenedLength)); return output; } - #endregion - #region Broadcast + #region BroadcastTo + /// + /// Broadcast the data from to . + /// + /// Input . + /// + public static void BroadcastTo(this Tensor source, in TensorSpan destination) + { + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(source.Lengths, destination.Lengths); + if (!destination.Lengths.SequenceEqual(newSize)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); + + ReadOnlyTensorSpan intermediate = LazyBroadcast(source, newSize); + intermediate.FlattenTo(MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength)); + } /// - /// Broadcast the data from to the smallest broadcastable shape compatible with . Creates a new and allocates new memory. + /// Broadcast the data from to . /// - /// Input . - /// Other to make shapes broadcastable. - public static Tensor Broadcast(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators + /// Input . + /// Other to make shapes broadcastable. + public static void BroadcastTo(in this TensorSpan source, in TensorSpan destination) { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(source.Lengths, destination.Lengths); + if (!destination.Lengths.SequenceEqual(newSize)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); - Tensor intermediate = BroadcastTo(left, newSize); - return Tensor.Create(intermediate.ToArray(), intermediate.Lengths); + ReadOnlyTensorSpan intermediate = LazyBroadcast(source, newSize); + intermediate.FlattenTo(MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength)); } /// - /// Broadcast the data from to the new shape . Creates a new and allocates new memory. - /// If the shape of the is not compatible with the new shape, an exception is thrown. + /// Broadcast the data from to . /// - /// Input . - /// of the desired new shape. - /// Thrown when the shapes are not broadcast compatible. - public static Tensor Broadcast(Tensor input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators + /// Input . + /// + public static void BroadcastTo(in this ReadOnlyTensorSpan source, in TensorSpan destination) { - Tensor intermediate = BroadcastTo(input, shape); - return Tensor.Create(intermediate.ToArray(), intermediate.Lengths); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(source.Lengths, destination.Lengths); + if (!destination.Lengths.SequenceEqual(newSize)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); + + ReadOnlyTensorSpan intermediate = LazyBroadcast(source, newSize); + intermediate.FlattenTo(MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength)); } // Lazy/non-copy broadcasting, internal only for now. @@ -78,16 +122,15 @@ public static Tensor Broadcast(Tensor input, ReadOnlySpan shape) /// but no memory is allocated. It manipulates the strides to achieve this affect. /// If the shape of the is not compatible with the new shape, an exception is thrown. /// - /// Input . + /// Input . /// of the desired new shape. /// Thrown when the shapes are not broadcast compatible. - internal static Tensor BroadcastTo(Tensor input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators + internal static TensorSpan LazyBroadcast(in TensorSpan input, ReadOnlySpan shape) { if (input.Lengths.SequenceEqual(shape)) - return new Tensor(input._values, shape, false); + return new TensorSpan(ref input._reference, shape, input.Strides, input._memoryLength); - if (!TensorHelpers.AreShapesBroadcastCompatible(input.Lengths, shape)) + if (!TensorHelpers.IsBroadcastableTo(input.Lengths, shape)) ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); @@ -111,259 +154,205 @@ internal static Tensor BroadcastTo(Tensor input, ReadOnlySpan sha } } - Tensor output = new Tensor(input._values, shape, strides); + TensorSpan output = new TensorSpan(ref input._reference, shape, strides, input._memoryLength); return output; } - #endregion - - #region Reverse + // Lazy/non-copy broadcasting, internal only for now. /// - /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. - /// defaults to -1 when not provided, which reverses the entire tensor. + /// Broadcast the data from to the new shape . Creates a new + /// but no memory is allocated. It manipulates the strides to achieve this affect. + /// If the shape of the is not compatible with the new shape, an exception is thrown. /// - /// Input . - /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left tensor. - public static Tensor Reverse(Tensor input, nint axis = -1) - where T : IEquatable, IEqualityOperators + /// Input . + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + internal static ReadOnlyTensorSpan LazyBroadcast(in ReadOnlyTensorSpan input, ReadOnlySpan shape) { - T[] values = input.IsPinned ? GC.AllocateArray((int)input._flattenedLength) : (new T[input._flattenedLength]); - Tensor output = new Tensor(values, input.Lengths.ToArray(), input.Strides.ToArray()); - if (axis == -1) - { - int index = 0; - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input.FlattenedLength); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output.FlattenedLength); - for (int i = (int)input.FlattenedLength - 1; i >= 0; i--) - { - ospan[index++] = span[i]; - } - } - else - { - nint copyLength = 1; - for (nint i = axis; i < input.Lengths.Length; i++) - { - copyLength *= input.Lengths[(int)i]; - } - copyLength /= input.Lengths[(int)axis]; + if (input.Lengths.SequenceEqual(shape)) + return new TensorSpan(ref input._reference, shape, input.Strides, input._memoryLength); - scoped Span oIndices; - nint[]? oIndicesArray; - scoped Span iIndices; - nint[]? iIndicesArray; - if (input.Rank > 6) - { - oIndicesArray = ArrayPool.Shared.Rent(input.Rank); - oIndices = oIndicesArray; - iIndicesArray = ArrayPool.Shared.Rent(input.Rank); - iIndices = iIndicesArray; - } - else - { - oIndicesArray = null; - oIndices = stackalloc nint[input.Rank]; - iIndicesArray = null; - iIndices = stackalloc nint[input.Rank]; - } + if (!TensorHelpers.IsBroadcastableTo(input.Lengths, shape)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); - iIndices[(int)axis] = input.Lengths[(int)axis] - 1; - nint copiedValues = 0; - TensorSpan islice = input.AsTensorSpan().Slice(input.Lengths); - TensorSpan oslice = output.AsTensorSpan().Slice(output._lengths); - while (copiedValues < input._flattenedLength) - { - TensorSpanHelpers.Memmove(ref Unsafe.Add(ref oslice._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, input.Strides, input.Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); - TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, input._lengths); - TensorSpanHelpers.AdjustIndexesDown((int)axis, 1, iIndices, input._lengths); - copiedValues += copyLength; - } + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); - if (oIndicesArray != null && iIndicesArray != null) + if (newSize == input.FlattenedLength) + return Reshape(input, shape); + + nint[] intermediateShape = TensorHelpers.GetIntermediateShape(input.Lengths, shape.Length); + nint[] strides = new nint[shape.Length]; + + nint stride = 1; + + for (int i = strides.Length - 1; i >= 0; i--) + { + if ((intermediateShape[i] == 1 && shape[i] != 1) || (intermediateShape[i] == 1 && shape[i] == 1)) + strides[i] = 0; + else { - ArrayPool.Shared.Return(oIndicesArray); - ArrayPool.Shared.Return(iIndicesArray); + strides[i] = stride; + stride *= intermediateShape[i]; } } + TensorSpan output = new TensorSpan(ref input._reference, shape, strides, input._memoryLength); + return output; } - #endregion - #region Split + // Lazy/non-copy broadcasting, internal only for now. /// - /// Split a into along the given . If the tensor cannot be split - /// evenly on the given an exception is thrown. + /// Broadcast the data from to the new shape . Creates a new + /// but no memory is allocated. It manipulates the strides to achieve this affect. + /// If the shape of the is not compatible with the new shape, an exception is thrown. /// /// Input . - /// How many times to split the - /// The axis to split on. - public static Tensor[] Split(Tensor input, nint numSplits, nint axis) - where T : IEquatable, IEqualityOperators + /// of the desired new shape. + /// Thrown when the shapes are not broadcast compatible. + internal static Tensor LazyBroadcast(Tensor input, ReadOnlySpan lengths) { - if (input.Lengths[(int)axis] % numSplits != 0) - ThrowHelper.ThrowArgument_SplitNotSplitEvenly(); + if (input.Lengths.SequenceEqual(lengths)) + return new Tensor(input._values, lengths, false); - Tensor[] outputs = new Tensor[numSplits]; + if (!TensorHelpers.IsBroadcastableTo(input.Lengths, lengths)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); - nint totalToCopy = input.FlattenedLength / numSplits; - nint copyLength = 1; - for (nint i = axis; i < input.Lengths.Length; i++) - { - copyLength *= input.Lengths[(int)i]; - } - copyLength /= numSplits; - nint[] newShape = input.Lengths.ToArray(); - newShape[(int)axis] = newShape[(int)axis] / numSplits; + nint newSize = TensorSpanHelpers.CalculateTotalLength(lengths); - scoped Span oIndices; - nint[]? oIndicesArray; - scoped Span iIndices; - nint[]? iIndicesArray; - if (input.Rank > 6) - { - oIndicesArray = ArrayPool.Shared.Rent(input.Rank); - oIndices = oIndicesArray; - iIndicesArray = ArrayPool.Shared.Rent(input.Rank); - iIndices = iIndicesArray; - } - else - { - oIndicesArray = null; - oIndices = stackalloc nint[input.Rank]; - iIndicesArray = null; - iIndices = stackalloc nint[input.Rank]; - } + if (newSize == input.FlattenedLength) + return Reshape(input, lengths); - for (int i = 0; i < outputs.Length; i++) - { - T[] values = input.IsPinned ? GC.AllocateArray((int)totalToCopy) : (new T[(int)totalToCopy]); - outputs[i] = new Tensor(values, newShape); - oIndices.Clear(); - iIndices.Clear(); + nint[] intermediateShape = TensorHelpers.GetIntermediateShape(input.Lengths, lengths.Length); + nint[] strides = new nint[lengths.Length]; - iIndices[(int)axis] = i; - TensorSpan islice = input.AsTensorSpan().Slice(input.Lengths); - TensorSpan oslice = outputs[i].AsTensorSpan().Slice(outputs[i]._lengths); + nint stride = 1; - nint copiedValues = 0; - while (copiedValues < totalToCopy) + for (int i = strides.Length - 1; i >= 0; i--) + { + if ((intermediateShape[i] == 1 && lengths[i] != 1) || (intermediateShape[i] == 1 && lengths[i] == 1)) + strides[i] = 0; + else { - TensorSpanHelpers.Memmove(ref Unsafe.Add(ref oslice._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, outputs[0].Strides, outputs[0].Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); - TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, outputs[i]._lengths); - TensorSpanHelpers.AdjustIndexes((int)axis - 1, 1, iIndices, input._lengths); - copiedValues += copyLength; + strides[i] = stride; + stride *= intermediateShape[i]; } } - if (oIndicesArray != null && iIndicesArray != null) - { - ArrayPool.Shared.Return(oIndicesArray); - ArrayPool.Shared.Return(iIndicesArray); - } + Tensor output = new Tensor(input._values, lengths, strides); - return outputs; + return output; } #endregion - #region SetSlice - // REVIEW: WHAT DO WE WANT TO CALL THIS? COPYTO? IT DOES FIT IN WITH THE EXISTING COPY TO CONVENTIONS FOR VECTOR (albeit backwards). + #region Concatenate /// - /// Sets a slice of the given with the provided for the given + /// Join a sequence of tensors along an existing axis. /// - /// Input . - /// The values you want to set in the . - /// The ranges you want to set. - public static Tensor SetSlice(this Tensor tensor, Tensor values, params ReadOnlySpan ranges) - where T : IEquatable, IEqualityOperators + /// The tensors must have the same shape, except in the dimension corresponding to axis (the first, by default). + /// The axis along which the tensors will be joined. If axis is -1, arrays are flattened before use. Default is 0. + public static Tensor Concatenate(scoped ReadOnlySpan> tensors, int axis = 0) { - TensorSpan srcSpan; - if (ranges == ReadOnlySpan.Empty) - { - if (!tensor.Lengths.SequenceEqual(values.Lengths)) - ThrowHelper.ThrowArgument_SetSliceNoRange(nameof(values)); - srcSpan = tensor.AsTensorSpan().Slice(tensor.Lengths); - } - else - srcSpan = tensor.AsTensorSpan().Slice(ranges); - - if (!srcSpan.Lengths.SequenceEqual(values.Lengths)) - ThrowHelper.ThrowArgument_SetSliceInvalidShapes(nameof(values)); - - values.AsTensorSpan().CopyTo(srcSpan); - - return tensor; - } - #endregion + if (tensors.Length < 2) + ThrowHelper.ThrowArgument_ConcatenateTooFewTensors(); - #region FilteredUpdate - // REVIEW: PYTORCH/NUMPY DO THIS. - // t0[t0 < 2] = -1; - // OR SHOULD THIS BE AN OVERLOAD OF FILL THAT TAKES IN A FUNC TO KNOW WHICH ONE TO UPDATE? - /// - /// Updates the tensor with the where the is true. - /// - /// Input . - /// Input filter where if the index is true then it will update the . - /// Value to update in the . - public static Tensor FilteredUpdate(Tensor tensor, Tensor filter, T value) - where T : IEquatable, IEqualityOperators - { - if (filter.Lengths.Length != tensor.Lengths.Length) - ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); + if (axis < -1 || axis > tensors[0].Rank) + ThrowHelper.ThrowArgument_InvalidAxis(); - Span srcSpan = MemoryMarshal.CreateSpan(ref tensor._values[0], (int)tensor._flattenedLength); - Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)tensor._flattenedLength); + // Calculate total space needed. + nint totalLength = 0; + for (int i = 0; i < tensors.Length; i++) + totalLength += TensorSpanHelpers.CalculateTotalLength(tensors[i].Lengths); - for (int i = 0; i < filterSpan.Length; i++) + nint sumOfAxis = 0; + // If axis != -1, make sure all dimensions except the one to concatenate on match. + if (axis != -1) { - if (filterSpan[i]) + sumOfAxis = tensors[0].Lengths[axis]; + for (int i = 1; i < tensors.Length; i++) { - srcSpan[i] = value; + if (tensors[0].Rank != tensors[i].Rank) + ThrowHelper.ThrowArgument_InvalidConcatenateShape(); + for (int j = 0; j < tensors[0].Rank; j++) + { + if (j != axis) + { + if (tensors[0].Lengths[j] != tensors[i].Lengths[j]) + ThrowHelper.ThrowArgument_InvalidConcatenateShape(); + } + } + sumOfAxis += tensors[i].Lengths[axis]; } } - return tensor; - } + T[] values = tensors[0].IsPinned ? GC.AllocateArray((int)totalLength, tensors[0].IsPinned) : (new T[totalLength]); + Span dstSpan = MemoryMarshal.CreateSpan(ref values[0], (int)totalLength); + nint valuesCopied = 0; - /// - /// Updates the tensor with the where the is true. - /// If dmesions are not the same an exception is thrown. - /// - /// Input . - /// Input filter where if the index is true then it will update the . - /// Values to update in the . - public static Tensor FilteredUpdate(Tensor tensor, Tensor filter, Tensor values) - where T : IEquatable, IEqualityOperators - { - if (filter.Lengths.Length != tensor.Lengths.Length) - ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); - if (values.Rank != 1) - ThrowHelper.ThrowArgument_1DTensorRequired(nameof(values)); - - nint numTrueElements = TensorHelpers.CountTrueElements(filter); - if (numTrueElements != values._flattenedLength) - ThrowHelper.ThrowArgument_IncorrectNumberOfFilterItems(nameof(values)); + scoped Span curIndex; + nint[]? curIndexArray; - Span dstSpan = MemoryMarshal.CreateSpan(ref tensor._values[0], (int)tensor._flattenedLength); - Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)tensor._flattenedLength); - Span valuesSpan = MemoryMarshal.CreateSpan(ref values._values[0], (int)values._flattenedLength); + if (tensors[0].Rank > 6) + { + curIndexArray = ArrayPool.Shared.Rent(tensors[0].Rank); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[tensors[0].Rank]; + } + nint srcIndex; + nint copyLength; - int index = 0; - for (int i = 0; i < filterSpan.Length; i++) + while (valuesCopied < totalLength) { - if (filterSpan[i]) + for (int i = 0; i < tensors.Length; i++) { - dstSpan[i] = valuesSpan[index++]; + srcIndex = TensorSpanHelpers.ComputeLinearIndex(curIndex, tensors[i].Strides, tensors[i].Lengths); + copyLength = CalculateCopyLength(tensors[i].Lengths, axis); + Span srcSpan = MemoryMarshal.CreateSpan(ref tensors[i]._values[srcIndex], (int)copyLength); + TensorSpanHelpers.Memmove(dstSpan, srcSpan, copyLength, valuesCopied); + valuesCopied += copyLength; } + TensorSpanHelpers.AdjustIndexes(axis - 1, 1, curIndex, tensors[0].Lengths); + } + + Tensor tensor; + if (axis == -1) + { + tensor = new Tensor(values, [valuesCopied], tensors[0].IsPinned); } + else + { + nint[] lengths = new nint[tensors[0].Rank]; + tensors[0].Lengths.CopyTo(lengths); + lengths[axis] = sumOfAxis; + tensor = new Tensor(values, lengths, tensors[0].IsPinned); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); return tensor; } + + private static nint CalculateCopyLength(ReadOnlySpan lengths, int startingAxis) + { + // When starting axis is -1 we want all the data at once same as if starting axis is 0 + if (startingAxis == -1) + startingAxis = 0; + nint length = 1; + for (int i = startingAxis; i < lengths.Length; i++) + { + length *= lengths[i]; + } + return length; + } #endregion - #region SequenceEqual + #region ElementwiseEqual /// /// Compares the elements of two for equality. If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size /// before they are compared. It returns a where the value is true if the elements are equal and false if they are not."/> @@ -371,11 +360,11 @@ public static Tensor FilteredUpdate(Tensor tensor, Tensor filter, /// First to compare. /// Second to compare. /// A where the value is true if the elements are equal and false if they are not. - public static Tensor SequenceEqual(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators + public static Tensor ElementwiseEqual(Tensor left, Tensor right) + where T : IEqualityOperators { Tensor result; - if (TensorHelpers.AreShapesTheSame(left, right)) + if (TensorHelpers.AreLengthsTheSame(left, right)) { result = Tensor.Create(left.Lengths, false); @@ -386,10 +375,10 @@ public static Tensor SequenceEqual(Tensor left, Tensor right) } else { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); result = Tensor.Create(newSize, false); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); scoped Span curIndex; nint[]? curIndexArray; @@ -417,111 +406,55 @@ public static Tensor SequenceEqual(Tensor left, Tensor right) return result; } - #endregion - #region LessThan /// - /// Compares the elements of two to see which elements of are less than . - /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. - /// It returns a where the value is true if the elements in are less than - /// and false if they are not."/> + /// Compares the elements of two for equality. If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size + /// before they are compared. It returns a where the value is true if the elements are equal and false if they are not."/> /// /// First to compare. /// Second to compare. - /// A where the value is true if the elements in are less than and - /// false if they are not. - public static Tensor LessThan(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + /// + /// A where the value is true if the elements are equal and false if they are not. + public static ref readonly TensorSpan ElementwiseEqual(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IEqualityOperators { - Tensor result; - if (TensorHelpers.AreShapesTheSame(left, right)) - { - result = Tensor.Create(left.Lengths, false); - - for (int i = 0; i < left.FlattenedLength; i++) - { - result._values[i] = left._values[i] < right._values[i]; - } - } - else + Span result = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + if (TensorHelpers.AreLengthsTheSame(left, right)) { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - result = Tensor.Create(newSize, false); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + if (!TensorHelpers.AreLengthsTheSame(destination.Lengths, left.Lengths)) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(destination)); scoped Span curIndex; nint[]? curIndexArray; - if (broadcastedRight.Lengths.Length > 6) + if (left.Rank > 6) { - curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndexArray = ArrayPool.Shared.Rent(left.Lengths.Length); curIndex = curIndexArray; } else { curIndexArray = null; - curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + curIndex = stackalloc nint[left.Lengths.Length]; } - for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + for (int i = 0; i < left.FlattenedLength; i++) { - result._values[i] = broadcastedLeft[curIndex] < broadcastedRight[curIndex]; - TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + result[i] = left[curIndex] == right[curIndex]; + TensorSpanHelpers.AdjustIndexes(left.Rank - 1, 1, curIndex, left.Lengths); } if (curIndexArray != null) ArrayPool.Shared.Return(curIndexArray); } - - return result; - } - - /// - /// Compares the elements of a to see which elements are less than . - /// It returns a where the value is true if the elements in are less than - /// and false if they are not."/> - /// - /// to compare. - /// to compare against . - /// where the value is true if the elements in are less than - /// and false if they are not. - public static Tensor LessThan(Tensor left, T right) - where T : IEquatable, IEqualityOperators, IComparisonOperators - { - Tensor result = Tensor.Create(left.Lengths, false); - - for (int i = 0; i < left.FlattenedLength; i++) - { - result._values[i] = left._values[i] < right; - } - return result; - } - - /// - /// Compares the elements of two to see if any elements of are less than . - /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. - /// It returns a where the value is true if any elements in are less than . - /// - /// First to compare. - /// Second to compare against. - /// where the value is true if any elements in are less than . - public static bool LessThanAny(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators - { - if (TensorHelpers.AreShapesTheSame(left, right)) - { - for (int i = 0; i < left.FlattenedLength; i++) - { - if (left._values[i] < right._values[i]) - return true; - } - } else { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + if (!TensorHelpers.AreLengthsTheSame(destination.Lengths, newSize)) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(destination)); + + ReadOnlyTensorSpan broadcastedLeft = LazyBroadcast(left, newSize); + ReadOnlyTensorSpan broadcastedRight = LazyBroadcast(right, newSize); scoped Span curIndex; nint[]? curIndexArray; @@ -539,8 +472,7 @@ public static bool LessThanAny(Tensor left, Tensor right) for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) { - if (broadcastedLeft[curIndex] < broadcastedRight[curIndex]) - return true; + result[i] = broadcastedLeft[curIndex] == broadcastedRight[curIndex]; TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); } @@ -548,59 +480,71 @@ public static bool LessThanAny(Tensor left, Tensor right) ArrayPool.Shared.Return(curIndexArray); } - return false; + return ref destination; } + #endregion + #region FilteredUpdate + // REVIEW: PYTORCH/NUMPY DO THIS. + // t0[t0 < 2] = -1; + // OR SHOULD THIS BE AN OVERLOAD OF FILL THAT TAKES IN A FUNC TO KNOW WHICH ONE TO UPDATE? /// - /// Compares the elements of two to see if all elements of are less than . - /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. - /// It returns a where the value is true if all elements in are less than . + /// Updates the tensor with the where the is true. /// - /// First to compare. - /// Second to compare against. - /// where the value is true if all elements in are less than . - public static bool LessThanAll(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + /// Input . + /// Input filter where if the index is true then it will update the . + /// Value to update in the . + public static TensorSpan FilteredUpdate(in this TensorSpan tensor, scoped in ReadOnlyTensorSpan filter, T value) { - if (TensorHelpers.AreShapesTheSame(left, right)) + if (filter.Lengths.Length != tensor.Lengths.Length) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); + + Span srcSpan = MemoryMarshal.CreateSpan(ref tensor._reference, (int)tensor._flattenedLength); + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._reference, (int)tensor._flattenedLength); + + for (int i = 0; i < filterSpan.Length; i++) { - for (int i = 0; i < left.FlattenedLength; i++) + if (filterSpan[i]) { - if (left._values[i] > right._values[i]) - return false; + srcSpan[i] = value; } } - else - { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); - scoped Span curIndex; - nint[]? curIndexArray; + return tensor; + } - if (broadcastedRight.Lengths.Length > 6) - { - curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); - curIndex = curIndexArray; - } - else - { - curIndexArray = null; - curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; - } + /// + /// Updates the tensor with the where the is true. + /// If dmesions are not the same an exception is thrown. + /// + /// Input . + /// Input filter where if the index is true then it will update the . + /// Values to update in the . + public static TensorSpan FilteredUpdate(in this TensorSpan tensor, scoped in ReadOnlyTensorSpan filter, scoped in ReadOnlyTensorSpan values) + { + if (filter.Lengths.Length != tensor.Lengths.Length) + ThrowHelper.ThrowArgument_DimensionsNotSame(nameof(filter)); + if (values.Rank != 1) + ThrowHelper.ThrowArgument_1DTensorRequired(nameof(values)); - for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + nint numTrueElements = TensorHelpers.CountTrueElements(filter); + if (numTrueElements != values._flattenedLength) + ThrowHelper.ThrowArgument_IncorrectNumberOfFilterItems(nameof(values)); + + Span dstSpan = MemoryMarshal.CreateSpan(ref tensor._reference, (int)tensor._flattenedLength); + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._reference, (int)tensor._flattenedLength); + Span valuesSpan = MemoryMarshal.CreateSpan(ref values._reference, (int)values._flattenedLength); + + int index = 0; + for (int i = 0; i < filterSpan.Length; i++) + { + if (filterSpan[i]) { - if (broadcastedLeft[curIndex] > broadcastedRight[curIndex]) - return false; - TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + dstSpan[i] = valuesSpan[index++]; } - - if (curIndexArray != null) - ArrayPool.Shared.Return(curIndexArray); } - return true; + + return tensor; } #endregion @@ -616,10 +560,10 @@ public static bool LessThanAll(Tensor left, Tensor right) /// A where the value is true if the elements in are greater than and /// false if they are not. public static Tensor GreaterThan(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + where T : IComparisonOperators { Tensor result; - if (TensorHelpers.AreShapesTheSame(left, right)) + if (TensorHelpers.AreLengthsTheSame(left, right)) { result = Tensor.Create(left.Lengths, false); @@ -630,10 +574,10 @@ public static Tensor GreaterThan(Tensor left, Tensor right) } else { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); result = Tensor.Create(newSize, false); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); scoped Span curIndex; nint[]? curIndexArray; @@ -672,7 +616,7 @@ public static Tensor GreaterThan(Tensor left, Tensor right) /// where the value is true if the elements in are greater than /// and false if they are not. public static Tensor GreaterThan(Tensor left, T right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + where T : IComparisonOperators { Tensor result = Tensor.Create(left.Lengths, false); @@ -692,9 +636,9 @@ public static Tensor GreaterThan(Tensor left, T right) /// Second to compare against. /// where the value is true if any elements in are greater than . public static bool GreaterThanAny(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + where T : IComparisonOperators { - if (TensorHelpers.AreShapesTheSame(left, right)) + if (TensorHelpers.AreLengthsTheSame(left, right)) { for (int i = 0; i < left.FlattenedLength; i++) @@ -705,9 +649,9 @@ public static bool GreaterThanAny(Tensor left, Tensor right) } else { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); scoped Span curIndex; nint[]? curIndexArray; @@ -745,9 +689,9 @@ public static bool GreaterThanAny(Tensor left, Tensor right) /// Second to compare against. /// where the value is true if all elements in are greater than . public static bool GreaterThanAll(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IComparisonOperators + where T : IComparisonOperators { - if (TensorHelpers.AreShapesTheSame(left, right)) + if (TensorHelpers.AreLengthsTheSame(left, right)) { for (int i = 0; i < left.FlattenedLength; i++) @@ -758,9 +702,9 @@ public static bool GreaterThanAll(Tensor left, Tensor right) } else { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - Tensor broadcastedLeft = BroadcastTo(left, newSize); - Tensor broadcastedRight = BroadcastTo(right, newSize); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); scoped Span curIndex; nint[]? curIndexArray; @@ -790,67 +734,645 @@ public static bool GreaterThanAll(Tensor left, Tensor right) } #endregion - #region Stack - // REVIEW: NEEDS A DIFFERENT NAME? - // JUST AN OVERLOAD FOR CONCATENATE? + #region LessThan /// - /// Join an array of along a new axis. The axis parameter specifies the index of the new axis in the dimensions of the result and - /// defaults to 0. All tensors must have the same shape. + /// Compares the elements of two to see which elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if the elements in are less than + /// and false if they are not."/> /// - /// Array of . - /// Index of where the new axis will be. Defaults to 0. - public static Tensor Stack(Tensor[] input, int axis = 0) - where T : IEquatable, IEqualityOperators + /// First to compare. + /// Second to compare. + /// A where the value is true if the elements in are less than and + /// false if they are not. + public static Tensor LessThan(Tensor left, Tensor right) + where T : IComparisonOperators { - if (input.Length < 2) - ThrowHelper.ThrowArgument_StackTooFewTensors(); - if (axis < 0) - axis = input.Rank - axis; - - Tensor[] outputs = new Tensor[input.Length]; - for (int i = 0; i < input.Length; i++) + Tensor result; + if (TensorHelpers.AreLengthsTheSame(left, right)) { - outputs[i] = Tensor.Unsqueeze(input[0], axis); + result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] < right._values[i]; + } } - return Tensor.Concatenate(outputs, axis); - } - #endregion + else + { + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + result = Tensor.Create(newSize, false); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); - #region Reshape - // REVIEW: SENTINAL VALUE? CONSTANT VALUE FOR -1 WILDCARD? - /// + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + result._values[i] = broadcastedLeft[curIndex] < broadcastedRight[curIndex]; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return result; + } + + /// + /// Compares the elements of a to see which elements are less than . + /// It returns a where the value is true if the elements in are less than + /// and false if they are not."/> + /// + /// to compare. + /// to compare against . + /// where the value is true if the elements in are less than + /// and false if they are not. + public static Tensor LessThan(Tensor left, T right) + where T : IComparisonOperators + { + Tensor result = Tensor.Create(left.Lengths, false); + + for (int i = 0; i < left.FlattenedLength; i++) + { + result._values[i] = left._values[i] < right; + } + return result; + } + + /// + /// Compares the elements of two to see if any elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if any elements in are less than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if any elements in are less than . + public static bool LessThanAny(Tensor left, Tensor right) + where T : IComparisonOperators + { + if (TensorHelpers.AreLengthsTheSame(left, right)) + { + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] < right._values[i]) + return true; + } + } + else + { + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] < broadcastedRight[curIndex]) + return true; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + + return false; + } + + /// + /// Compares the elements of two to see if all elements of are less than . + /// If the shapes are not the same, the tensors are broadcasted to the smallest broadcastable size before they are compared. + /// It returns a where the value is true if all elements in are less than . + /// + /// First to compare. + /// Second to compare against. + /// where the value is true if all elements in are less than . + public static bool LessThanAll(Tensor left, Tensor right) + where T : IComparisonOperators + { + if (TensorHelpers.AreLengthsTheSame(left, right)) + { + for (int i = 0; i < left.FlattenedLength; i++) + { + if (left._values[i] > right._values[i]) + return false; + } + } + else + { + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + Tensor broadcastedLeft = LazyBroadcast(left, newSize); + Tensor broadcastedRight = LazyBroadcast(right, newSize); + + scoped Span curIndex; + nint[]? curIndexArray; + + if (broadcastedRight.Lengths.Length > 6) + { + curIndexArray = ArrayPool.Shared.Rent(broadcastedRight.Lengths.Length); + curIndex = curIndexArray; + } + else + { + curIndexArray = null; + curIndex = stackalloc nint[broadcastedRight.Lengths.Length]; + } + + for (int i = 0; i < broadcastedLeft.FlattenedLength; i++) + { + if (broadcastedLeft[curIndex] > broadcastedRight[curIndex]) + return false; + TensorSpanHelpers.AdjustIndexes(broadcastedRight.Rank - 1, 1, curIndex, broadcastedRight.Lengths); + } + + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); + } + return true; + } + #endregion + + #region Mean + /// + /// Returns the mean of the elements in the tensor. + /// + /// The to take the mean of. + /// representing the mean. + public static T Mean(scoped in ReadOnlyTensorSpan input) + where T : IFloatingPoint + { + T sum = Sum(input); + return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); + } + #endregion + + #region Permute + + /// + /// Swaps the dimensions of the tensor according to the parameter. + /// If is a 1D tensor, it will return . Otherwise it creates a new + /// with the new axis ordering by allocating new memory. + /// + /// Input + /// with the new axis ordering. + public static Tensor Permute(this Tensor input, params ReadOnlySpan axis) + { + if (input.Rank == 1) + { + return input; + } + else + { + T[] values = input.IsPinned ? GC.AllocateArray((int)input._flattenedLength) : (new T[input._flattenedLength]); + nint[] lengths = new nint[input.Rank]; + Tensor tensor; + TensorSpan ospan; + TensorSpan ispan; + ReadOnlySpan permutation; + + if (axis.IsEmpty) + { + lengths = input._lengths.Reverse().ToArray(); + permutation = Enumerable.Range(0, input.Rank).Reverse().ToArray(); + } + else + { + if (axis.Length != input.Lengths.Length) + ThrowHelper.ThrowArgument_PermuteAxisOrder(); + for (int i = 0; i < lengths.Length; i++) + lengths[i] = input.Lengths[axis[i]]; + permutation = axis.ToArray(); + } + tensor = new Tensor(values, lengths, Array.Empty(), input._isPinned); + + ospan = tensor.AsTensorSpan(); + ispan = input.AsTensorSpan(); + + scoped Span indexes; + nint[]? indicesArray; + scoped Span permutedIndices; + nint[]? permutedIndicesArray; + if (tensor.Rank > 6) + { + indicesArray = ArrayPool.Shared.Rent(tensor.Rank); + indexes = indicesArray; + permutedIndicesArray = ArrayPool.Shared.Rent(tensor.Rank); + permutedIndices = permutedIndicesArray; + } + else + { + indicesArray = null; + indexes = stackalloc nint[tensor.Rank]; + permutedIndicesArray = null; + permutedIndices = stackalloc nint[tensor.Rank]; + } + + for (int i = 0; i < input._flattenedLength; i++) + { + TensorHelpers.PermuteIndices(indexes, permutedIndices, permutation); + ospan[permutedIndices] = ispan[indexes]; + TensorSpanHelpers.AdjustIndexes(tensor.Rank - 1, 1, indexes, input._lengths); + } + + if (indicesArray != null && permutedIndicesArray != null) + { + ArrayPool.Shared.Return(indicesArray); + ArrayPool.Shared.Return(permutedIndicesArray); + } + + return tensor; + } + } + #endregion + + #region Reshape + // REVIEW: SENTINAL VALUE? CONSTANT VALUE FOR -1 WILDCARD? + /// + /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. + /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, + /// an exception is thrown. + /// + /// you want to reshape. + /// with the new dimensions. + public static Tensor Reshape(this Tensor input, params ReadOnlySpan lengths) + { + nint[] arrLengths = lengths.ToArray(); + // Calculate wildcard info. + if (lengths.Contains(-1)) + { + if (lengths.Count(-1) > 1) + ThrowHelper.ThrowArgument_OnlyOneWildcard(); + nint tempTotal = input._flattenedLength; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] != -1) + { + tempTotal /= lengths[i]; + } + } + arrLengths[lengths.IndexOf(-1)] = tempTotal; + + } + + nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); + if (tempLinear != input.FlattenedLength) + ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); + nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); + return new Tensor(input._values, arrLengths, strides); + } + + /// + /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. + /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, + /// an exception is thrown. + /// + /// you want to reshape. + /// with the new dimensions. + public static TensorSpan Reshape(this in TensorSpan input, params scoped ReadOnlySpan lengths) + { + nint[] arrLengths = lengths.ToArray(); + // Calculate wildcard info. + if (lengths.Contains(-1)) + { + if (lengths.Count(-1) > 1) + ThrowHelper.ThrowArgument_OnlyOneWildcard(); + nint tempTotal = input.FlattenedLength; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] != -1) + { + tempTotal /= lengths[i]; + } + } + arrLengths[lengths.IndexOf(-1)] = tempTotal; + + } + + nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); + if (tempLinear != input.FlattenedLength) + ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); + nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); + TensorSpan output = new TensorSpan(ref input._reference, arrLengths, strides, input._memoryLength); + return output; + } + + /// /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, /// an exception is thrown. /// - /// you want to reshape. - /// with the new dimensions. - public static Tensor Reshape(this Tensor input, params ReadOnlySpan lengths) - where T : IEquatable, IEqualityOperators + /// you want to reshape. + /// with the new dimensions. + public static ReadOnlyTensorSpan Reshape(this in ReadOnlyTensorSpan input, params scoped ReadOnlySpan lengths) + { + nint[] arrLengths = lengths.ToArray(); + // Calculate wildcard info. + if (lengths.Contains(-1)) + { + if (lengths.Count(-1) > 1) + ThrowHelper.ThrowArgument_OnlyOneWildcard(); + nint tempTotal = input.FlattenedLength; + for (int i = 0; i < lengths.Length; i++) + { + if (lengths[i] != -1) + { + tempTotal /= lengths[i]; + } + } + arrLengths[lengths.IndexOf(-1)] = tempTotal; + + } + + nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); + if (tempLinear != input.FlattenedLength) + ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); + nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); + ReadOnlyTensorSpan output = new ReadOnlyTensorSpan(ref input._reference, arrLengths, strides, input._memoryLength); + return output; + } + #endregion + + #region Resize + /// + /// Creates a new , allocates new memory, and copies the data from . If the final shape is smaller all data after + /// that point is ignored. + /// + /// Input . + /// of the desired new shape. + public static Tensor Resize(Tensor input, ReadOnlySpan shape) + { + nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); + T[] values = input.IsPinned ? GC.AllocateArray((int)newSize) : (new T[newSize]); + Tensor output = new Tensor(values, shape, false); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input.AsTensorSpan()._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); + if (newSize > input.FlattenedLength) + TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); + else + TensorSpanHelpers.Memmove(ospan, span, newSize); + + return output; + } + + /// + /// Copies the data from . If the final shape is smaller all data after that point is ignored. + /// If the final shape is bigger it is filled with 0s. + /// + /// Input . + /// Destination with the desired new shape. + public static ref readonly TensorSpan Resize(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + if (destination.FlattenedLength > input.FlattenedLength) + TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); + else + TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); + + return ref destination; + } + #endregion + + #region Reverse + /// + /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. + /// defaults to -1 when not provided, which reverses the entire tensor. + /// + /// Input . + /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left tensor. + public static Tensor Reverse(in ReadOnlyTensorSpan input, nint axis = -1) + { + Tensor output = Tensor.Create(input.Lengths); + Reverse(input, output, axis); + + return output; + } + + /// + /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. + /// defaults to -1 when not provided, which reverses the entire span. + /// + /// Input . + /// + /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left span. + public static ref readonly TensorSpan Reverse(scoped in ReadOnlyTensorSpan input, in TensorSpan destination, nint axis = -1) + { + if (axis == -1) + { + nint index = input.FlattenedLength - 1; + Span inputSpan = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span outputSpan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + for (int i = 0; i <= input.FlattenedLength / 2; i++) + { + outputSpan[i] = inputSpan[(int)index]; + outputSpan[(int)index--] = inputSpan[i]; + } + } + else + { + nint copyLength = 1; + for (nint i = axis; i < input.Lengths.Length; i++) + { + copyLength *= input.Lengths[(int)i]; + } + copyLength /= input.Lengths[(int)axis]; + + scoped Span oIndices; + nint[]? oIndicesArray; + scoped Span iIndices; + nint[]? iIndicesArray; + if (input.Rank > 6) + { + oIndicesArray = ArrayPool.Shared.Rent(input.Rank); + oIndices = oIndicesArray; + iIndicesArray = ArrayPool.Shared.Rent(input.Rank); + iIndices = iIndicesArray; + } + else + { + oIndicesArray = null; + oIndices = stackalloc nint[input.Rank]; + iIndicesArray = null; + iIndices = stackalloc nint[input.Rank]; + } + + iIndices[(int)axis] = input.Lengths[(int)axis] - 1; + nint copiedValues = 0; + ReadOnlyTensorSpan islice = input.Slice(input.Lengths); + + while (copiedValues < input.FlattenedLength) + { + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref destination._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, input.Strides, input.Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); + TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, input.Lengths); + TensorSpanHelpers.AdjustIndexesDown((int)axis, 1, iIndices, input.Lengths); + copiedValues += copyLength; + } + //TensorSpanHelpers.Memmove(ref input._reference, ref values[0], input.FlattenedLength); + + if (oIndicesArray != null && iIndicesArray != null) + { + ArrayPool.Shared.Return(oIndicesArray); + ArrayPool.Shared.Return(iIndicesArray); + } + } + + return ref destination; + } + #endregion + + #region SequenceEqual + + /// + /// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T). + /// + public static bool SequenceEqual(this scoped in ReadOnlyTensorSpan span, scoped in ReadOnlyTensorSpan other) + { + return span.FlattenedLength == other.FlattenedLength + && MemoryMarshal.CreateReadOnlySpan(in span.GetPinnableReference(), (int)span.FlattenedLength).SequenceEqual(MemoryMarshal.CreateReadOnlySpan(in other.GetPinnableReference(), (int)other.FlattenedLength)); + } + #endregion + + #region SetSlice + // REVIEW: WHAT DO WE WANT TO CALL THIS? COPYTO? IT DOES FIT IN WITH THE EXISTING COPY TO CONVENTIONS FOR VECTOR (albeit backwards). + /// + /// Sets a slice of the given with the provided for the given + /// + /// Input . + /// The values you want to set in the . + /// The ranges you want to set. + public static Tensor SetSlice(this Tensor tensor, in ReadOnlyTensorSpan values, params ReadOnlySpan ranges) + { + SetSlice((TensorSpan)tensor, values, ranges); + + return tensor; + } + + /// + /// Sets a slice of the given with the provided for the given + /// + /// Input . + /// The values you want to set in the . + /// The ranges you want to set. + public static ref readonly TensorSpan SetSlice(this in TensorSpan tensor, scoped in ReadOnlyTensorSpan values, params scoped ReadOnlySpan ranges) { - nint[] arrLengths = lengths.ToArray(); - // Calculate wildcard info. - if (lengths.Contains(-1)) + TensorSpan srcSpan; + if (ranges == ReadOnlySpan.Empty) { - if (lengths.Count(-1) > 1) - ThrowHelper.ThrowArgument_OnlyOneWildcard(); - nint tempTotal = input._flattenedLength; - for (int i = 0; i < lengths.Length; i++) + if (!tensor.Lengths.SequenceEqual(values.Lengths)) + ThrowHelper.ThrowArgument_SetSliceNoRange(nameof(values)); + srcSpan = tensor.Slice(tensor.Lengths); + } + else + srcSpan = tensor.Slice(ranges); + + if (!srcSpan.Lengths.SequenceEqual(values.Lengths)) + ThrowHelper.ThrowArgument_SetSliceInvalidShapes(nameof(values)); + + values.CopyTo(srcSpan); + + return ref tensor; + } + #endregion + + #region Split + /// + /// Split a into along the given . If the tensor cannot be split + /// evenly on the given an exception is thrown. + /// + /// Input . + /// How many times to split the + /// The axis to split on. + public static Tensor[] Split(scoped in ReadOnlyTensorSpan input, nint numSplits, nint axis) + { + if (input.Lengths[(int)axis] % numSplits != 0) + ThrowHelper.ThrowArgument_SplitNotSplitEvenly(); + + Tensor[] outputs = new Tensor[numSplits]; + + nint totalToCopy = input.FlattenedLength / numSplits; + nint copyLength = 1; + for (nint i = axis; i < input.Lengths.Length; i++) + { + copyLength *= input.Lengths[(int)i]; + } + copyLength /= numSplits; + nint[] newShape = input.Lengths.ToArray(); + newShape[(int)axis] = newShape[(int)axis] / numSplits; + + scoped Span oIndices; + nint[]? oIndicesArray; + scoped Span iIndices; + nint[]? iIndicesArray; + if (input.Rank > 6) + { + oIndicesArray = ArrayPool.Shared.Rent(input.Rank); + oIndices = oIndicesArray; + iIndicesArray = ArrayPool.Shared.Rent(input.Rank); + iIndices = iIndicesArray; + } + else + { + oIndicesArray = null; + oIndices = stackalloc nint[input.Rank]; + iIndicesArray = null; + iIndices = stackalloc nint[input.Rank]; + } + + for (int i = 0; i < outputs.Length; i++) + { + T[] values = new T[(int)totalToCopy]; + outputs[i] = new Tensor(values, newShape); + oIndices.Clear(); + iIndices.Clear(); + + iIndices[(int)axis] = i; + ReadOnlyTensorSpan islice = input.Slice(input.Lengths); + TensorSpan oslice = outputs[i].AsTensorSpan().Slice(outputs[i]._lengths); + + nint copiedValues = 0; + while (copiedValues < totalToCopy) { - if (lengths[i] != -1) - { - tempTotal /= lengths[i]; - } + TensorSpanHelpers.Memmove(ref Unsafe.Add(ref oslice._reference, TensorSpanHelpers.ComputeLinearIndex(oIndices, outputs[0].Strides, outputs[0].Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); + TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, outputs[i]._lengths); + TensorSpanHelpers.AdjustIndexes((int)axis - 1, 1, iIndices, input._lengths); + copiedValues += copyLength; } - arrLengths[lengths.IndexOf(-1)] = tempTotal; + } + if (oIndicesArray != null && iIndicesArray != null) + { + ArrayPool.Shared.Return(oIndicesArray); + ArrayPool.Shared.Return(iIndicesArray); } - nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); - if (tempLinear != input.FlattenedLength) - ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); - nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); - return new Tensor(input._values, arrLengths, strides); + return outputs; } #endregion @@ -862,8 +1384,7 @@ public static Tensor Reshape(this Tensor input, params ReadOnlySpan /// The to remove axis of length 1. /// The axis to remove. Defaults to -1 which removes all axis of length 1. - public static Tensor Squeeze(Tensor input, int axis = -1) - where T : IEquatable, IEqualityOperators + public static Tensor Squeeze(this Tensor input, int axis = -1) { if (axis >= input.Rank) ThrowHelper.ThrowArgument_AxisLargerThanRank(); @@ -903,135 +1424,129 @@ public static Tensor Squeeze(Tensor input, int axis = -1) return new Tensor(input._values, lengths, strides); } - #endregion - #region Unsqueeze - // REVIEW: NAME? NUMPY CALLS THIS expand_dims. /// - /// Insert a new axis of length 1 that will appear at the axis position. + /// Removes axis of length one from the . defaults to -1 and will remove all axis with length of 1. + /// If is specified, it will only remove that axis and if it is not of length one it will throw an exception. /// - /// The to remove axis of length 1. - /// The axis to add. - public static Tensor Unsqueeze(Tensor input, int axis) - where T : IEquatable, IEqualityOperators + /// The to remove axis of length 1. + /// The axis to remove. Defaults to -1 which removes all axis of length 1. + public static TensorSpan Squeeze(in this TensorSpan input, int axis = -1) { - if (axis > input.Lengths.Length) + if (axis >= input.Rank) ThrowHelper.ThrowArgument_AxisLargerThanRank(); - if (axis < 0) - axis = input.Rank - axis; - List tempLengths = input._lengths.ToList(); - tempLengths.Insert(axis, 1); - nint[] lengths = tempLengths.ToArray(); - nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); - return new Tensor(input._values, lengths, strides); + nint[] lengths; + nint[] strides; + + List tempLengths = new List(); + if (axis == -1) + { + for (int i = 0; i < input.Lengths.Length; i++) + { + if (input.Lengths[i] != 1) + { + tempLengths.Add(input.Lengths[i]); + } + } + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); + } + else + { + if (input.Lengths[axis] != 1) + { + ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); + } + for (int i = 0; i < input.Lengths.Length; i++) + { + if (i != axis) + { + tempLengths.Add(input.Lengths[i]); + } + } + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); + } + + return new TensorSpan(ref input._reference, lengths, strides, input._memoryLength); } - #endregion - #region Concatenate /// - /// Join a sequence of tensors along an existing axis. + /// Removes axis of length one from the . defaults to -1 and will remove all axis with length of 1. + /// If is specified, it will only remove that axis and if it is not of length one it will throw an exception. /// - /// The tensors must have the same shape, except in the dimension corresponding to axis (the first, by default). - /// The axis along which the tensors will be joined. If axis is -1, arrays are flattened before use. Default is 0. - public static Tensor Concatenate(ReadOnlySpan> tensors, int axis = 0) - where T : IEquatable, IEqualityOperators + /// The to remove axis of length 1. + /// The axis to remove. Defaults to -1 which removes all axis of length 1. + public static ReadOnlyTensorSpan Squeeze(in this ReadOnlyTensorSpan input, int axis = -1) { - if (tensors.Length < 2) - ThrowHelper.ThrowArgument_ConcatenateTooFewTensors(); - - if (axis < -1 || axis > tensors[0].Rank) - ThrowHelper.ThrowArgument_InvalidAxis(); + if (axis >= input.Rank) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); - // Calculate total space needed. - nint totalLength = 0; - for (int i = 0; i < tensors.Length; i++) - totalLength += TensorSpanHelpers.CalculateTotalLength(tensors[i].Lengths); + nint[] lengths; + nint[] strides; - nint sumOfAxis = 0; - // If axis != -1, make sure all dimensions except the one to concatenate on match. - if (axis != -1) + List tempLengths = new List(); + if (axis == -1) { - sumOfAxis = tensors[0].Lengths[axis]; - for (int i = 1; i < tensors.Length; i++) + for (int i = 0; i < input.Lengths.Length; i++) { - if (tensors[0].Rank != tensors[i].Rank) - ThrowHelper.ThrowArgument_InvalidConcatenateShape(); - for (int j = 0; j < tensors[0].Rank; j++) + if (input.Lengths[i] != 1) { - if (j != axis) - { - if (tensors[0].Lengths[j] != tensors[i].Lengths[j]) - ThrowHelper.ThrowArgument_InvalidConcatenateShape(); - } + tempLengths.Add(input.Lengths[i]); } - sumOfAxis += tensors[i].Lengths[axis]; } - } - - T[] values = tensors[0].IsPinned ? GC.AllocateArray((int)totalLength, tensors[0].IsPinned) : (new T[totalLength]); - Span dstSpan = MemoryMarshal.CreateSpan(ref values[0], (int)totalLength); - nint valuesCopied = 0; - - scoped Span curIndex; - nint[]? curIndexArray; - - if (tensors[0].Rank > 6) - { - curIndexArray = ArrayPool.Shared.Rent(tensors[0].Rank); - curIndex = curIndexArray; + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); } else { - curIndexArray = null; - curIndex = stackalloc nint[tensors[0].Rank]; - } - nint srcIndex; - nint copyLength; - - while (valuesCopied < totalLength) - { - for (int i = 0; i < tensors.Length; i++) + if (input.Lengths[axis] != 1) { - srcIndex = TensorSpanHelpers.ComputeLinearIndex(curIndex, tensors[i].Strides, tensors[i].Lengths); - copyLength = CalculateCopyLength(tensors[i].Lengths, axis); - Span srcSpan = MemoryMarshal.CreateSpan(ref tensors[i]._values[srcIndex], (int)copyLength); - TensorSpanHelpers.Memmove(dstSpan, srcSpan, copyLength, valuesCopied); - valuesCopied += copyLength; + ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); } - TensorSpanHelpers.AdjustIndexes(axis - 1, 1, curIndex, tensors[0].Lengths); + for (int i = 0; i < input.Lengths.Length; i++) + { + if (i != axis) + { + tempLengths.Add(input.Lengths[i]); + } + } + lengths = tempLengths.ToArray(); + strides = TensorSpanHelpers.CalculateStrides(lengths); } - Tensor tensor; - if (axis == -1) - { - tensor = new Tensor(values, [valuesCopied], tensors[0].IsPinned); - } - else + return new ReadOnlyTensorSpan(ref input._reference, lengths, strides, input._memoryLength); + } + #endregion + + #region Stack + /// + /// Join an array of along a new axis. The axis parameter specifies the index of the new axis in the dimensions of the result and + /// defaults to 0. All tensors must have the same shape. + /// + /// Array of . + /// Index of where the new axis will be. Defaults to 0. + public static Tensor Stack(ReadOnlySpan> input, int axis = 0) + { + if (input.Length < 2) + ThrowHelper.ThrowArgument_StackTooFewTensors(); + + for (int i = 1; i < input.Length; i++) { - nint[] lengths = new nint[tensors[0].Rank]; - tensors[0].Lengths.CopyTo(lengths); - lengths[axis] = sumOfAxis; - tensor = new Tensor(values, lengths, tensors[0].IsPinned); + if (!TensorHelpers.AreLengthsTheSame(input[0], input[i])) + ThrowHelper.ThrowArgument_StackShapesNotSame(); } - if (curIndexArray != null) - ArrayPool.Shared.Return(curIndexArray); - - return tensor; - } + if (axis < 0) + axis = input[0].Rank - axis; - private static nint CalculateCopyLength(ReadOnlySpan lengths, int startingAxis) - { - // When starting axis is -1 we want all the data at once same as if starting axis is 0 - if (startingAxis == -1) - startingAxis = 0; - nint length = 1; - for (int i = startingAxis; i < lengths.Length; i++) + Tensor[] outputs = new Tensor[input.Length]; + for (int i = 0; i < input.Length; i++) { - length *= lengths[i]; + outputs[i] = Tensor.Unsqueeze(input[0], axis); } - return length; + return Tensor.Concatenate(outputs, axis); } #endregion @@ -1039,14 +1554,13 @@ private static nint CalculateCopyLength(ReadOnlySpan lengths, int starting /// /// Returns the standard deviation of the elements in the tensor. /// - /// The to take the standard deviation of. + /// The to take the standard deviation of. /// representing the standard deviation. - public static T StdDev(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity - + public static T StdDev(in ReadOnlyTensorSpan input) + where T : IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity { T mean = Mean(input); - Span span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); + Span span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); Span output = new T[input._flattenedLength].AsSpan(); TensorPrimitives.Subtract(span, mean, output); TensorPrimitives.Abs(output, output); @@ -1054,66 +1568,67 @@ public static T StdDev(Tensor input) T sum = TensorPrimitives.Sum((ReadOnlySpan)output); return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); } + #endregion + #region ToString /// - /// Return the standard deviation of the elements in the tensor. Casts the return value to . + /// Creates a representation of the ."/> /// - /// The to take the standard deviation of. - /// representing the standard deviation. - public static TResult StdDev(Tensor input) - where T : IEquatable, IEqualityOperators, INumber, IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity - where TResult : IEquatable, IEqualityOperators, IFloatingPoint - - { - T mean = Mean(input); - Span span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Span output = new T[input._flattenedLength].AsSpan(); - TensorPrimitives.Subtract(span, mean, output); - TensorPrimitives.Abs(output, output); - TensorPrimitives.Pow((ReadOnlySpan)output, T.CreateChecked(2), output); - T sum = TensorPrimitives.Sum((ReadOnlySpan)output); - return TResult.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); - } + /// The you want to represent as a string. + /// Maximum Length of each dimension + /// A representation of the + public static string ToString(this in TensorSpan span, params ReadOnlySpan maximumLengths) => ((ReadOnlyTensorSpan)span).ToString(maximumLengths); - #endregion - - #region Mean /// - /// Returns the mean of the elements in the tensor. + /// Creates a representation of the ."/> /// - /// The to take the mean of. - /// representing the mean. - public static T Mean(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// + /// The you want to represent as a string. + /// Maximum Length of each dimension + public static string ToString(this in ReadOnlyTensorSpan span, params ReadOnlySpan maximumLengths) + { + var sb = new StringBuilder(); + scoped Span curIndexes; + nint[]? curIndexesArray; + if (span.Rank > 6) + { + curIndexesArray = ArrayPool.Shared.Rent(span.Rank); + curIndexes = curIndexesArray; + } + else + { + curIndexesArray = null; + curIndexes = stackalloc nint[span.Rank]; + } - { - T sum = Sum(input); - return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); - } + nint copiedValues = 0; - /// - /// Return the mean of the elements in the tensor. Casts the return value to . - /// - /// The to take the mean of. - /// representing the mean. - public static TResult Mean(Tensor input) - where T : IEquatable, IEqualityOperators, INumber - where TResult : IEquatable, IEqualityOperators, IFloatingPoint + T[] values = new T[span.Lengths[span.Rank - 1]]; + while (copiedValues < span._flattenedLength) + { + var sp = new ReadOnlyTensorSpan(ref Unsafe.Add(ref span._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, span.Strides, span.Lengths)), [span.Lengths[span.Rank - 1]], [1], span.Lengths[span.Rank - 1]); + sb.Append('{'); + sp.FlattenTo(values); + sb.Append(string.Join(",", values)); + sb.AppendLine("}"); + + TensorSpanHelpers.AdjustIndexes(span.Rank - 2, 1, curIndexes, span._lengths); + copiedValues += span.Lengths[span.Rank - 1]; + } - { - T sum = Sum(input); - return TResult.CreateChecked(TResult.CreateChecked(sum) / TResult.CreateChecked(input.FlattenedLength)); - } + if (curIndexesArray != null) + ArrayPool.Shared.Return(curIndexesArray); + return sb.ToString(); + } #endregion - #region Permute/Transpose + #region Transpose /// /// Swaps the last two dimensions of the tensor. /// /// Input . public static Tensor Transpose(Tensor input) - where T : IEquatable, IEqualityOperators { if (input.Lengths.Length < 2) ThrowHelper.ThrowArgument_TransposeTooFewDimensions(); @@ -1123,82 +1638,110 @@ public static Tensor Transpose(Tensor input) axis[input.Rank - 2] = temp; return Permute(input, axis.AsSpan()); } + #endregion + #region TryBroadcastTo /// - /// Swaps the dimensions of the tensor according to the parameter. - /// If is a 1D tensor, it will return . Otherwise it creates a new - /// with the new axis ordering by allocating new memory. + /// Broadcast the data from to the smallest broadcastable shape compatible with and stores it in + /// If the shapes are not compatible, false is returned. /// - /// Input - /// with the new axis ordering. - public static Tensor Permute(Tensor input, params ReadOnlySpan axis) - where T : IEquatable, IEqualityOperators + /// Input . + /// Destination . + public static bool TryBroadcastTo(this Tensor input, in TensorSpan destination) { - if (input.Rank == 1) - { - return input; - } - else - { - T[] values = input.IsPinned ? GC.AllocateArray((int)input._flattenedLength) : (new T[input._flattenedLength]); - nint[] lengths = new nint[input.Rank]; - Tensor tensor; - TensorSpan ospan; - TensorSpan ispan; - ReadOnlySpan permutation; + return TryBroadcastTo((ReadOnlyTensorSpan)input, destination); + } - if (axis.IsEmpty) - { - lengths = input._lengths.Reverse().ToArray(); - permutation = Enumerable.Range(0, input.Rank).Reverse().ToArray(); - } - else - { - if (axis.Length != input.Lengths.Length) - ThrowHelper.ThrowArgument_PermuteAxisOrder(); - for (int i = 0; i < lengths.Length; i++) - lengths[i] = input.Lengths[axis[i]]; - permutation = axis.ToArray(); - } - tensor = new Tensor(values, lengths, Array.Empty(), input._isPinned); + /// + /// Broadcast the data from to the smallest broadcastable shape compatible with and stores it in + /// If the shapes are not compatible, false is returned. + /// + /// Input . + /// Destination . + public static bool TryBroadcastTo(in this TensorSpan input, in TensorSpan destination) + { + return TryBroadcastTo((ReadOnlyTensorSpan)input, destination); + } - ospan = tensor.AsTensorSpan(); - ispan = input.AsTensorSpan(); + /// + /// Broadcast the data from to the smallest broadcastable shape compatible with and stores it in + /// If the shapes are not compatible, false is returned. + /// + /// Input . + /// Destination . + public static bool TryBroadcastTo(in this ReadOnlyTensorSpan input, in TensorSpan destination) + { + if (!TensorHelpers.IsBroadcastableTo(input.Lengths, destination.Lengths)) + return false; - scoped Span indexes; - nint[]? indicesArray; - scoped Span permutedIndices; - nint[]? permutedIndicesArray; - if (tensor.Rank > 6) - { - indicesArray = ArrayPool.Shared.Rent(tensor.Rank); - indexes = indicesArray; - permutedIndicesArray = ArrayPool.Shared.Rent(tensor.Rank); - permutedIndices = permutedIndicesArray; - } - else - { - indicesArray = null; - indexes = stackalloc nint[tensor.Rank]; - permutedIndicesArray = null; - permutedIndices = stackalloc nint[tensor.Rank]; - } + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(input.Lengths, destination.Lengths); + if (!TensorHelpers.AreLengthsTheSame(destination.Lengths, newSize)) + return false; - for (int i = 0; i < input._flattenedLength; i++) - { - TensorHelpers.PermuteIndices(indexes, permutedIndices, permutation); - ospan[permutedIndices] = ispan[indexes]; - TensorSpanHelpers.AdjustIndexes(tensor.Rank - 1, 1, indexes, input._lengths); - } + LazyBroadcast(input, newSize).CopyTo(destination); + return true; + } + #endregion - if (indicesArray != null && permutedIndicesArray != null) - { - ArrayPool.Shared.Return(indicesArray); - ArrayPool.Shared.Return(permutedIndicesArray); - } + #region Unsqueeze + // REVIEW: NAME? NUMPY CALLS THIS expand_dims. + /// + /// Insert a new axis of length 1 that will appear at the axis position. + /// + /// The to remove axis of length 1. + /// The axis to add. + public static Tensor Unsqueeze(this Tensor input, int axis) + { + if (axis > input.Lengths.Length) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); + if (axis < 0) + axis = input.Rank - axis; - return tensor; - } + List tempLengths = input._lengths.ToList(); + tempLengths.Insert(axis, 1); + nint[] lengths = tempLengths.ToArray(); + nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); + return new Tensor(input._values, lengths, strides); + } + + // REVIEW: NAME? NUMPY CALLS THIS expand_dims. + /// + /// Insert a new axis of length 1 that will appear at the axis position. + /// + /// The to remove axis of length 1. + /// The axis to add. + public static TensorSpan Unsqueeze(in this TensorSpan input, int axis) + { + if (axis > input.Lengths.Length) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); + if (axis < 0) + axis = input.Rank - axis; + + List tempLengths = input._lengths.ToArray().ToList(); + tempLengths.Insert(axis, 1); + nint[] lengths = tempLengths.ToArray(); + nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); + return new TensorSpan(ref input._reference, lengths, strides, input._memoryLength); + } + + // REVIEW: NAME? NUMPY CALLS THIS expand_dims. + /// + /// Insert a new axis of length 1 that will appear at the axis position. + /// + /// The to remove axis of length 1. + /// The axis to add. + public static ReadOnlyTensorSpan Unsqueeze(in this ReadOnlyTensorSpan input, int axis) + { + if (axis > input.Lengths.Length) + ThrowHelper.ThrowArgument_AxisLargerThanRank(); + if (axis < 0) + axis = input.Rank - axis; + + List tempLengths = input._lengths.ToArray().ToList(); + tempLengths.Insert(axis, 1); + nint[] lengths = tempLengths.ToArray(); + nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); + return new ReadOnlyTensorSpan(ref input._reference, lengths, strides, input._memoryLength); } #endregion @@ -1207,21 +1750,24 @@ public static Tensor Permute(Tensor input, params ReadOnlySpan axi /// /// Takes the absolute value of each element of the and returns a new with the result. /// - /// The to take the sin of. + /// The to take the abs of. public static Tensor Abs(Tensor input) - where T : IEquatable, IEqualityOperators, INumberBase + where T : INumberBase { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Abs); + Tensor output = Tensor.Create(input.Lengths); + Abs(input, output); + return output; } /// - /// Takes the absolute of each element of the in place. + /// Takes the absolute value of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AbsInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, INumberBase + /// The to take the abs of. + /// The destination. + public static ref readonly TensorSpan Abs(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : INumberBase { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Abs, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Abs); } #endregion @@ -1231,19 +1777,22 @@ public static Tensor AbsInPlace(Tensor input) /// /// The to take the sin of. public static Tensor Acos(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acos); + Tensor output = Tensor.Create(input.Lengths); + Acos(input, output); + return output; } /// - /// Takes the inverse cosine of each element of the in place. + /// Takes the inverse cosine of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AcosInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Acos(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acos, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Acos); } #endregion @@ -1253,19 +1802,22 @@ public static Tensor AcosInPlace(Tensor input) /// /// The to take the sin of. public static Tensor Acosh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acosh); + Tensor output = Tensor.Create(input.Lengths); + Acosh(input, output); + return output; } /// - /// Takes the inverse hyperbolic cosine of each element of the in place. + /// Takes the inverse hyperbolic cosine of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AcoshInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Acosh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acosh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Acosh); } #endregion @@ -1275,19 +1827,22 @@ public static Tensor AcoshInPlace(Tensor input) /// /// The to take the sin of. public static Tensor AcosPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AcosPi); + Tensor output = Tensor.Create(input.Lengths); + AcosPi(input, output); + return output; } /// - /// Takes the inverse hyperbolic cosine divided by pi of each element of the in place. + /// Takes the inverse hyperbolic cosine divided by pi of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AcosPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan AcosPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AcosPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.AcosPi); } #endregion @@ -1298,20 +1853,20 @@ public static Tensor AcosPiInPlace(Tensor input) /// The of values to add. /// The second of values to add. public static Tensor Add(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + where T : IAdditionOperators, IAdditiveIdentity { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Add); - } + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } - /// - /// Adds each element of to each element of in place. - /// - /// The of values to add. - /// The second of values to add. - public static Tensor AddInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Add, true); + Add(left, right, output); + return output; } /// @@ -1320,21 +1875,35 @@ public static Tensor AddInPlace(Tensor left, Tensor right) /// The of values to add. /// The to add to each element of . public static Tensor Add(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + where T : IAdditionOperators, IAdditiveIdentity { - return TensorPrimitivesHelperSpanInTInSpanOut(input, val, TensorPrimitives.Add); + Tensor output = Tensor.Create(input.Lengths); + Add(input, val, output); + return output; } /// - /// Adds to each element of in place. + /// Adds each element of to each element of and returns a new with the result. /// - /// The of values to add. - /// The to add to each element of . - public static Tensor AddInPlace(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + /// The of values to add. + /// The second of values to add. + /// + public static ref readonly TensorSpan Add(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IAdditionOperators, IAdditiveIdentity { - return TensorPrimitivesHelperSpanInTInSpanOut(input, val, TensorPrimitives.Add, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Add); + } + /// + /// Adds to each element of and returns a new with the result. + /// + /// The of values to add. + /// The to add to each element of . + /// + public static ref readonly TensorSpan Add(scoped in ReadOnlyTensorSpan input, T val, in TensorSpan destination) + where T : IAdditionOperators, IAdditiveIdentity + { + return ref TensorPrimitivesHelperSpanInTInSpanOut(input, val, destination, TensorPrimitives.Add); } #endregion @@ -1344,19 +1913,22 @@ public static Tensor AddInPlace(Tensor input, T val) /// /// The to take the sin of. public static Tensor Asin(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asin); + Tensor output = Tensor.Create(input.Lengths); + Asin(input, output); + return output; } /// - /// Takes the inverse sine each element of the in place. + /// Takes the inverse sin of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AsinInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Asin(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asin, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Asin); } #endregion @@ -1366,19 +1938,22 @@ public static Tensor AsinInPlace(Tensor input) /// /// The to take the sin of. public static Tensor Asinh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asinh); + Tensor output = Tensor.Create(input.Lengths); + Asinh(input, output); + return output; } /// - /// Takes the inverse hyperbolic sine each element of the in place. + /// Takes the inverse hyperbolic sine of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AsinhInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Asinh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asinh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Asinh); } #endregion @@ -1388,19 +1963,22 @@ public static Tensor AsinhInPlace(Tensor input) /// /// The to take the sin of. public static Tensor AsinPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AsinPi); + Tensor output = Tensor.Create(input.Lengths); + AsinPi(input, output); + return output; } /// - /// Takes the inverse hyperbolic sine divided by pi of each element of the in place. + /// Takes the inverse hyperbolic sine divided by pi of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor AsinPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan AsinPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AsinPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.AsinPi); } #endregion @@ -1410,19 +1988,22 @@ public static Tensor AsinPiInPlace(Tensor input) /// /// The input public static Tensor Atan(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atan); + Tensor output = Tensor.Create(input.Lengths); + Atan(input, output); + return output; } /// - /// Takes the arc tangent of each element of the in place. + /// Takes the arc tangent of each element of the and returns a new with the result. /// - /// The input - public static Tensor AtanInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The input + /// + public static ref readonly TensorSpan Atan(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atan, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Atan); } #endregion @@ -1433,20 +2014,32 @@ public static Tensor AtanInPlace(Tensor input) /// The left . /// The right . public static Tensor Atan2(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Atan2(left, right, output); + return output; } /// - /// Takes the arc tangent of the two input in place. + /// Takes the arc tangent of the two input and returns a new with the result. /// - /// The left . - /// The right . - public static Tensor Atan2InPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + /// The left . + /// The right . + /// + public static ref readonly TensorSpan Atan2(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Atan2); } #endregion @@ -1457,20 +2050,32 @@ public static Tensor Atan2InPlace(Tensor left, Tensor right) /// The left . /// The right . public static Tensor Atan2Pi(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2Pi); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Atan2Pi(left, right, output); + return output; } /// - /// Takes the arc tangent of the two input , divides each element by pi in place. + /// Takes the arc tangent of the two input , divides each element by pi, and returns a new with the result. /// - /// The left . - /// The right . - public static Tensor Atan2PiInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + /// The left . + /// The right . + /// + public static ref readonly TensorSpan Atan2Pi(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2Pi, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Atan2Pi); } #endregion @@ -1480,19 +2085,22 @@ public static Tensor Atan2PiInPlace(Tensor left, Tensor right) /// /// The input . public static Tensor Atanh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atanh); + Tensor output = Tensor.Create(input.Lengths); + Atanh(input, output); + return output; } /// - /// Takes the inverse hyperbolic tangent of each element of the in place. + /// Takes the inverse hyperbolic tangent of each element of the and returns a new with the result. /// - /// The input . - public static Tensor AtanhInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The input . + /// + public static ref readonly TensorSpan Atanh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atanh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Atanh); } #endregion @@ -1502,19 +2110,22 @@ public static Tensor AtanhInPlace(Tensor input) /// /// The input. public static Tensor AtanPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AtanPi); + Tensor output = Tensor.Create(input.Lengths); + AtanPi(input, output); + return output; } /// - /// Takes the inverse hyperbolic tangent divided by pi of each element of the in place. + /// Takes the inverse hyperbolic tangent divided by pi of each element of the and returns a new with the result. /// - /// The input. - public static Tensor AtanPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The input. + /// + public static ref readonly TensorSpan AtanPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AtanPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.AtanPi); } #endregion @@ -1525,20 +2136,32 @@ public static Tensor AtanPiInPlace(Tensor input) /// The left . /// The right . public static Tensor BitwiseAnd(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseAnd); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + BitwiseAnd(left, right, output); + return output; } /// - /// Computes the element-wise bitwise and of the two input in place. + /// Computes the element-wise bitwise and of the two input and returns a new with the result. /// - /// The left . - /// The right . - public static Tensor BitwiseAndInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + /// The left . + /// The right . + /// + public static ref readonly TensorSpan BitwiseAnd(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseAnd, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.BitwiseAnd); } #endregion @@ -1549,20 +2172,32 @@ public static Tensor BitwiseAndInPlace(Tensor left, Tensor right) /// The left . /// The right . public static Tensor BitwiseOr(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseOr); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + BitwiseOr(left, right, output); + return output; } /// - /// Computes the element-wise bitwise of of the two input in place. + /// Computes the element-wise bitwise of of the two input and returns a new with the result. /// - /// The left . - /// The right . - public static Tensor BitwiseOrInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + /// The left . + /// The right . + /// + public static ref readonly TensorSpan BitwiseOr(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseOr, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.BitwiseOr); } #endregion @@ -1571,20 +2206,23 @@ public static Tensor BitwiseOrInPlace(Tensor left, Tensor right) /// Computes the element-wise cube root of the input and returns a new with the result. /// /// The left . - public static Tensor CubeRoot(Tensor input) - where T : IEquatable, IEqualityOperators, IRootFunctions + public static Tensor Cbrt(Tensor input) + where T : IRootFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cbrt); + Tensor output = Tensor.Create(input.Lengths); + Cbrt(input, output); + return output; } /// - /// Computes the element-wise cube root of the input in place. + /// Computes the element-wise cube root of the input and returns a new with the result. /// - /// The left . - public static Tensor CubeRootInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IRootFunctions + /// The left . + /// + public static ref readonly TensorSpan Cbrt(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IRootFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cbrt, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Cbrt); } #endregion @@ -1594,19 +2232,22 @@ public static Tensor CubeRootInPlace(Tensor input) /// /// The left . public static Tensor Ceiling(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Ceiling); + Tensor output = Tensor.Create(input.Lengths); + Ceiling(input, output); + return output; } /// - /// Computes the element-wise ceiling of the input in place. + /// Computes the element-wise ceiling of the input and returns a new with the result. /// - /// The left . - public static Tensor CeilingInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// The left . + /// + public static ref readonly TensorSpan Ceiling(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Ceiling, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Ceiling); } #endregion @@ -1620,7 +2261,23 @@ public static Tensor ConvertChecked(Tensor source) where TFrom : IEquatable, IEqualityOperators, INumberBase where TTo : INumberBase { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertChecked); + Tensor output = Tensor.Create(source.Lengths); + + ConvertChecked(source, output); + return output; + } + + /// + /// Copies to a new converting each + /// value to a value. + /// + /// The input . + /// + public static ref readonly TensorSpan ConvertChecked(scoped in ReadOnlyTensorSpan source, in TensorSpan destination) + where TFrom : IEquatable, IEqualityOperators, INumberBase + where TTo : INumberBase + { + return ref TensorPrimitivesHelperTFromSpanInTToSpanOut(source, destination, TensorPrimitives.ConvertChecked); } #endregion @@ -1634,7 +2291,23 @@ public static Tensor ConvertSaturating(Tensor source) where TFrom : IEquatable, IEqualityOperators, INumberBase where TTo : INumberBase { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertSaturating); + Tensor output = Tensor.Create(source.Lengths); + + ConvertSaturating(source, output); + return output; + } + + /// + /// Copies to a new converting each + /// value to a value. + /// + /// The input . + /// + public static ref readonly TensorSpan ConvertSaturating(scoped in ReadOnlyTensorSpan source, in TensorSpan destination) + where TFrom : IEquatable, IEqualityOperators, INumberBase + where TTo : INumberBase + { + return ref TensorPrimitivesHelperTFromSpanInTToSpanOut(source, destination, TensorPrimitives.ConvertSaturating); } #endregion @@ -1648,7 +2321,23 @@ public static Tensor ConvertTruncating(Tensor source) where TFrom : IEquatable, IEqualityOperators, INumberBase where TTo : INumberBase { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertTruncating); + Tensor output = Tensor.Create(source.Lengths); + + ConvertTruncating(source, output); + return output; + } + + /// + /// Copies to a new converting each + /// value to a value. + /// + /// The input . + /// + public static ref readonly TensorSpan ConvertTruncating(scoped in ReadOnlyTensorSpan source, in TensorSpan destination) + where TFrom : IEquatable, IEqualityOperators, INumberBase + where TTo : INumberBase + { + return ref TensorPrimitivesHelperTFromSpanInTToSpanOut(source, destination, TensorPrimitives.ConvertTruncating); } #endregion @@ -1659,48 +2348,58 @@ public static Tensor ConvertTruncating(Tensor source) /// Input . /// The number with the associated sign. public static Tensor CopySign(Tensor input, T sign) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.CopySign(span, sign, ospan); + + CopySign(input, sign, output); return output; } /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors in place. + /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new with the result. /// /// Input . - /// The number with the associated sign. - public static Tensor CopySignInPlace(Tensor input, T sign) - where T : IEquatable, IEqualityOperators, INumber + /// The with the associated signs. + public static Tensor CopySign(Tensor input, Tensor sign) + where T : INumber { - Span span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - TensorPrimitives.CopySign(span, sign, span); - return input; + Tensor output; + if (input.Lengths.SequenceEqual(sign.Lengths)) + { + output = Tensor.Create(input.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(input.Lengths, sign.Lengths)); + } + + CopySign(input, sign, output); + return output; } /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new with the result. + /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new tensor with the result. /// - /// Input . - /// The with the associated signs. - public static Tensor CopySign(Tensor input, Tensor sign) - where T : IEquatable, IEqualityOperators, INumber + /// Input . + /// The number with the associated sign. + /// + public static ref readonly TensorSpan CopySign(scoped in ReadOnlyTensorSpan input, T sign, in TensorSpan destination) + where T : INumber { - return TensorPrimitivesHelperTwoSpanInSpanOut(input, sign, TensorPrimitives.CopySign); + return ref TensorPrimitivesHelperSpanInTInSpanOut(input, sign, destination, TensorPrimitives.CopySign); } /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors in place. + /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new with the result. /// - /// Input . - /// The with the associated signs. - public static Tensor CopySignInPlace(Tensor input, Tensor sign) - where T : IEquatable, IEqualityOperators, INumber + /// Input . + /// The with the associated signs. + /// + public static ref readonly TensorSpan CopySign(scoped in ReadOnlyTensorSpan input, scoped in ReadOnlyTensorSpan sign, in TensorSpan destination) + where T : INumber { - return TensorPrimitivesHelperTwoSpanInSpanOut(input, sign, TensorPrimitives.CopySign, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(input, sign, destination, TensorPrimitives.CopySign); } #endregion @@ -1710,19 +2409,22 @@ public static Tensor CopySignInPlace(Tensor input, Tensor sign) /// /// The to take the cosine of. public static Tensor Cos(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cos); + Tensor output = Tensor.Create(input.Lengths); + Cos(input, output); + return output; } /// - /// Takes the cosine of each element of the in place. + /// Takes the cosine of each element of the and returns a new with the result. /// - /// The to take the cosine of. - public static Tensor CosInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the cosine of. + /// + public static ref readonly TensorSpan Cos(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cos, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Cos); } #endregion @@ -1732,19 +2434,22 @@ public static Tensor CosInPlace(Tensor input) /// /// The to take the cosine of. public static Tensor Cosh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cosh); + Tensor output = Tensor.Create(input.Lengths); + Cosh(input, output); + return output; } /// - /// Takes the hyperbolic cosine of each element of the in place. + /// Takes the hyperbolic cosine of each element of the and returns a new with the result. /// - /// The to take the cosine of. - public static Tensor CoshInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The to take the cosine of. + /// + public static ref readonly TensorSpan Cosh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cosh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Cosh); } #endregion @@ -1755,7 +2460,7 @@ public static Tensor CoshInPlace(Tensor input) /// The first /// The second public static Tensor CosineSimilarity(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IRootFunctions + where T : IRootFunctions { if (left.Rank != 2) ThrowHelper.ThrowArgument_2DTensorRequired(nameof(left)); @@ -1793,6 +2498,50 @@ public static Tensor CosineSimilarity(Tensor left, Tensor right) } return Tensor.Create(values, [dim1, dim2]); + } + + public static ref readonly TensorSpan CosineSimilarity(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IRootFunctions + { + if (left.Rank != 2) + ThrowHelper.ThrowArgument_2DTensorRequired(nameof(left)); + + if (right.Rank != 2) + ThrowHelper.ThrowArgument_2DTensorRequired(nameof(right)); + + if (left.Lengths[1] != right.Lengths[1]) + ThrowHelper.ThrowArgument_IncompatibleDimensions(left.Lengths[1], right.Lengths[1]); + + nint dim1 = left.Lengths[0]; + nint dim2 = right.Lengths[0]; + + if (destination.Lengths[0] != dim1 || destination.Lengths[1] != dim2) + ThrowHelper.ThrowArgument_IncompatibleDimensions(left.Lengths[1], right.Lengths[1]); + + Span values = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination._flattenedLength); + + scoped Span leftIndexes = stackalloc nint[2]; + scoped Span rightIndexes = stackalloc nint[2]; + + int outputOffset = 0; + + ReadOnlySpan lspan; + ReadOnlySpan rspan; + int rowLength = (int)left.Lengths[1]; + for (int i = 0; i < dim1; i++) + { + for (int j = 0; j < dim2; j++) + { + lspan = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.Add(ref left._reference, TensorSpanHelpers.ComputeLinearIndex(leftIndexes, left.Strides, left.Lengths)), (int)rowLength); + rspan = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.Add(ref right._reference, TensorSpanHelpers.ComputeLinearIndex(rightIndexes, right.Strides, right.Lengths)), (int)rowLength); + values[outputOffset++] = TensorPrimitives.CosineSimilarity(lspan, rspan); + rightIndexes[0]++; + } + rightIndexes[0] = 0; + leftIndexes[0]++; + } + + return ref destination; } #endregion @@ -1813,13 +2562,16 @@ public static Tensor CosineSimilarity(Tensor left, Tensor right) /// /// public static Tensor CosPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.CosPi); + Tensor output = Tensor.Create(input.Lengths); + CosPi(input, output); + return output; } - /// Computes the element-wise cosine of the value in the specified tensor that has been multiplied by Pi in place. - /// The input + /// Computes the element-wise cosine of the value in the specified tensor that has been multiplied by Pi and returns a new with the results. + /// The input + /// /// /// /// This method effectively computes .CosPi([i]). @@ -1832,10 +2584,10 @@ public static Tensor CosPi(Tensor input) /// operating systems or architectures. /// /// - public static Tensor CosPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + public static ref readonly TensorSpan CosPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.CosPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.CosPi); } #endregion @@ -1845,19 +2597,22 @@ public static Tensor CosPiInPlace(Tensor input) /// /// The input . public static Tensor DegreesToRadians(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.DegreesToRadians); + Tensor output = Tensor.Create(input.Lengths); + DegreesToRadians(input, output); + return output; } /// - /// Computes the element-wise conversion of each number of degrees in the specified tensor to radians in place. + /// Computes the element-wise conversion of each number of degrees in the specified tensor to radians and returns a new tensor with the results. /// - /// The input . - public static Tensor DegreesToRadiansInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The input . + /// + public static ref readonly TensorSpan DegreesToRadians(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.DegreesToRadians, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.DegreesToRadians); } #endregion @@ -1868,11 +2623,21 @@ public static Tensor DegreesToRadiansInPlace(Tensor input) /// The input . /// The input . public static T Distance(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IRootFunctions + where T : IRootFunctions { - return TensorPrimitivesHelperTwoSpanInTOut(left, right, TensorPrimitives.Distance); + return Distance((ReadOnlyTensorSpan)left, right); } + /// + /// Computes the distance between two points, specified as non-empty, equal-length tensors of numbers, in Euclidean space. + /// + /// The input . + /// The input . + public static T Distance(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right) + where T : IRootFunctions + { + return TensorPrimitivesHelperTwoSpanInTOut(left, right, TensorPrimitives.Distance); + } #endregion #region Divide @@ -1882,81 +2647,90 @@ public static T Distance(Tensor left, Tensor right) /// Input . /// The divisor public static Tensor Divide(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IDivisionOperators + where T : IDivisionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Divide(span, val, ospan); + Divide(input, val, output); return output; } /// - /// Divides each element of by in place. + /// Divides by each element of and returns a new with the result."/> /// - /// Input . - /// The divisor. - public static Tensor DivideInPlace(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IDivisionOperators + /// The value to be divided. + /// The divisor. + public static Tensor Divide(T val, Tensor input) + where T : IDivisionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Divide(span, val, ospan); + Tensor output = Tensor.Create(input.Lengths, input.IsPinned); + Divide(val, input, output); return output; } /// - /// Divides by each element of and returns a new with the result."/> + /// Divides each element of by its corresponding element in and returns + /// a new with the result. /// - /// The value to be divided. - /// The divisor. - public static Tensor Divide(T val, Tensor input) - where T : IEquatable, IEqualityOperators, IDivisionOperators + /// The to be divided. + /// The divisor. + public static Tensor Divide(Tensor left, Tensor right) + where T : IDivisionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Divide(val, span, ospan); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Divide(left, right, output); return output; } /// - /// Divides by each element of in place. + /// Divides each element of by and returns a new with the result. /// - /// The value to be divided. - /// The divisor. - public static Tensor DivideInPlace(T val, Tensor input) - where T : IEquatable, IEqualityOperators, IDivisionOperators + /// Input . + /// The divisor + /// + public static ref readonly TensorSpan Divide(scoped in ReadOnlyTensorSpan input, T val, in TensorSpan destination) + where T : IDivisionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Divide(val, span, ospan); - return output; + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + TensorPrimitives.Divide(span, val, ospan); + return ref destination; } /// - /// Divides each element of by its corresponding element in and returns - /// a new with the result. + /// Divides by each element of and returns a new with the result."/> /// - /// The to be divided. - /// The divisor. - public static Tensor Divide(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IDivisionOperators + /// The value to be divided. + /// The divisor. + /// + public static ref readonly TensorSpan Divide(T val, scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IDivisionOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Divide); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + TensorPrimitives.Divide(val, span, ospan); + return ref destination; } /// - /// Divides each element of by its corresponding element in in place. + /// Divides each element of by its corresponding element in and returns + /// a new with the result. /// - /// The to be divided. - /// The divisor. - public static Tensor DivideInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IDivisionOperators + /// The to be divided. + /// The divisor. + /// + public static ref readonly TensorSpan Divide(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IDivisionOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Divide, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Divide); } #endregion @@ -1967,7 +2741,18 @@ public static Tensor DivideInPlace(Tensor left, Tensor right) /// The input . /// The input . public static T Dot(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity, IMultiplicativeIdentity, IMultiplyOperators + where T : IAdditionOperators, IAdditiveIdentity, IMultiplicativeIdentity, IMultiplyOperators + { + return Dot((ReadOnlyTensorSpan)left, right); + } + + /// + /// Computes the dot product of two tensors containing numbers. + /// + /// The input . + /// The input . + public static T Dot(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right) + where T : IAdditionOperators, IAdditiveIdentity, IMultiplicativeIdentity, IMultiplyOperators { return TensorPrimitivesHelperTwoSpanInTOut(left, right, TensorPrimitives.Dot); } @@ -1980,19 +2765,22 @@ public static T Dot(Tensor left, Tensor right) /// /// The input . public static Tensor Exp(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp); + Tensor output = Tensor.Create(input.Lengths); + Exp(input, output); + return output; } /// /// Computes the element-wise result of raising e to the single-precision floating-point number powers in the specified tensor. /// - /// The input . - public static Tensor ExpInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Exp(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Exp); } #endregion @@ -2002,19 +2790,22 @@ public static Tensor ExpInPlace(Tensor input) /// /// The input . public static Tensor Exp10(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10); + Tensor output = Tensor.Create(input.Lengths); + Exp10(input, output); + return output; } /// /// Computes the element-wise result of raising 10 to the number powers in the specified tensor. /// - /// The input . - public static Tensor Exp10InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Exp10(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Exp10); } #endregion @@ -2022,17 +2813,20 @@ public static Tensor Exp10InPlace(Tensor input) /// Computes the element-wise result of raising 10 to the number powers in the specified tensor, minus one. /// The input . public static Tensor Exp10M1(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10M1); + Tensor output = Tensor.Create(input.Lengths); + Exp10M1(input, output); + return output; } /// Computes the element-wise result of raising 10 to the number powers in the specified tensor, minus one. - /// The input . - public static Tensor Exp10M1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Exp10M1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10M1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Exp10M1); } #endregion @@ -2040,17 +2834,20 @@ public static Tensor Exp10M1InPlace(Tensor input) /// Computes the element-wise result of raising 2 to the number powers in the specified tensor. /// The input . public static Tensor Exp2(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2); + Tensor output = Tensor.Create(input.Lengths); + Exp2(input, output); + return output; } /// Computes the element-wise result of raising 2 to the number powers in the specified tensor. - /// The input . - public static Tensor Exp2InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Exp2(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Exp2); } #endregion @@ -2058,17 +2855,20 @@ public static Tensor Exp2InPlace(Tensor input) /// Computes the element-wise result of raising 2 to the number powers in the specified tensor, minus one. /// The input . public static Tensor Exp2M1(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2M1); + Tensor output = Tensor.Create(input.Lengths); + Exp2M1(input, output); + return output; } /// Computes the element-wise result of raising 2 to the number powers in the specified tensor, minus one. - /// The input . - public static Tensor Exp2M1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Exp2M1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2M1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Exp2M1); } #endregion @@ -2076,17 +2876,20 @@ public static Tensor Exp2M1InPlace(Tensor input) /// Computes the element-wise result of raising e to the number powers in the specified tensor, minus 1. /// The input . public static Tensor ExpM1(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.ExpM1); + Tensor output = Tensor.Create(input.Lengths); + ExpM1(input, output); + return output; } /// Computes the element-wise result of raising e to the number powers in the specified tensor, minus 1. - /// The input . - public static Tensor ExpM1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan ExpM1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.ExpM1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.ExpM1); } #endregion @@ -2094,17 +2897,20 @@ public static Tensor ExpM1InPlace(Tensor input) /// Computes the element-wise floor of numbers in the specified tensor. /// The input . public static Tensor Floor(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Floor); + Tensor output = Tensor.Create(input.Lengths); + Floor(input, output); + return output; } /// Computes the element-wise floor of numbers in the specified tensor. - /// The input . - public static Tensor FloorInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// The input . + /// + public static ref readonly TensorSpan Floor(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Floor, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Floor); } #endregion @@ -2115,22 +2921,34 @@ public static Tensor FloorInPlace(Tensor input) /// /// Left . /// Right . - public static Tensor Hypotenuse(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IRootFunctions + public static Tensor Hypot(Tensor left, Tensor right) + where T : IRootFunctions { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Hypot); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Hypot(left, right, output); + return output; } /// /// Computes the element-wise hypotenuse given values from two tensors representing the lengths of the shorter sides in a right-angled triangle. /// If the shapes are not the same they are broadcast to the smallest compatible shape. /// - /// Left . - /// Right . - public static Tensor HypotenuseInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IRootFunctions + /// Left . + /// Right . + /// + public static ref readonly TensorSpan Hypot(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IRootFunctions { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Hypot, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Hypot); } #endregion @@ -2140,31 +2958,52 @@ public static Tensor HypotenuseInPlace(Tensor left, Tensor right) /// Left . /// Right . public static Tensor Ieee754Remainder(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Ieee754Remainder); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Ieee754Remainder(left, right, output); + return output; } - /// /// Computes the element-wise remainder of the numbers in the specified tensors. /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left . - /// Right . - public static Tensor Ieee754RemainderInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + /// Left . + /// Right . + /// + public static ref readonly TensorSpan Ieee754Remainder(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Ieee754Remainder, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Ieee754Remainder); } #endregion #region ILogB - /// Computes the element-wise floor of numbers in the specified tensor. + /// Computes the element-wise integer logarithm of numbers in the specified tensor. /// The input . public static Tensor ILogB(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 + where T : IFloatingPointIeee754 + { + Tensor output = Tensor.Create(input.Lengths, input.Strides); + ILogB(input, output); + return output; + } + + /// Computes the element-wise integer logarithm of numbers in the specified tensor. + /// The input . + /// + public static ref readonly TensorSpan ILogB(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPointIeee754 { - return TensorPrimitivesHelperSpanInIntSpanOut(input, TensorPrimitives.ILogB); + return ref TensorPrimitivesHelperSpanInIntSpanOut(input, destination, TensorPrimitives.ILogB); } #endregion @@ -2172,36 +3011,66 @@ public static Tensor ILogB(Tensor input) /// Searches for the index of the largest number in the specified tensor. /// The input . public static int IndexOfMax(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber { ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); return TensorPrimitives.IndexOfMax(span); } + + /// Searches for the index of the largest number in the specified tensor. + /// The input . + public static int IndexOfMax(scoped in ReadOnlyTensorSpan input) + where T : INumber + + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + return TensorPrimitives.IndexOfMax(span); + } #endregion #region IndexOfMaxMagnitude /// Searches for the index of the number with the largest magnitude in the specified tensor. /// The input . public static int IndexOfMaxMagnitude(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber { ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); return TensorPrimitives.IndexOfMaxMagnitude(span); } + + /// Searches for the index of the number with the largest magnitude in the specified tensor. + /// The input . + public static int IndexOfMaxMagnitude(scoped in ReadOnlyTensorSpan input) + where T : INumber + + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + return TensorPrimitives.IndexOfMaxMagnitude(span); + } #endregion #region IndexOfMin /// Searches for the index of the smallest number in the specified tensor. /// The input . public static int IndexOfMin(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber { ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); return TensorPrimitives.IndexOfMin(span); } + + /// Searches for the index of the smallest number in the specified tensor. + /// The input . + public static int IndexOfMin(scoped in ReadOnlyTensorSpan input) + where T : INumber + + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + return TensorPrimitives.IndexOfMin(span); + } #endregion #region IndexOfMinMagnitude @@ -2210,12 +3079,24 @@ public static int IndexOfMin(Tensor input) /// /// The input . public static int IndexOfMinMagnitude(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber { ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); return TensorPrimitives.IndexOfMinMagnitude(span); } + + /// + /// Searches for the index of the number with the smallest magnitude in the specified tensor. + /// + /// The input . + public static int IndexOfMinMagnitude(scoped in ReadOnlyTensorSpan input) + where T : INumber + + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + return TensorPrimitives.IndexOfMinMagnitude(span); + } #endregion #region LeadingZeroCount @@ -2224,19 +3105,22 @@ public static int IndexOfMinMagnitude(Tensor input) /// /// The input . public static Tensor LeadingZeroCount(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LeadingZeroCount); + Tensor output = Tensor.Create(input.Lengths); + LeadingZeroCount(input, output); + return output; } /// /// Computes the element-wise leading zero count of numbers in the specified tensor. /// - /// The input . - public static Tensor LeadingZeroCountInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + /// The input . + /// + public static ref readonly TensorSpan LeadingZeroCount(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LeadingZeroCount, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.LeadingZeroCount); } #endregion @@ -2246,19 +3130,23 @@ public static Tensor LeadingZeroCountInPlace(Tensor input) /// /// The to take the natural logarithm of. public static Tensor Log(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log); + Tensor output = Tensor.Create(input.Lengths); + Log(input, output); + return output; } + /// - /// Takes the natural logarithm of each element of the in place. + /// Takes the natural logarithm of each element of the and returns a new with the result. /// - /// The to take the natural logarithm of. - public static Tensor LogInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the natural logarithm of. + /// + public static ref readonly TensorSpan Log(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Log); } #endregion @@ -2268,19 +3156,22 @@ public static Tensor LogInPlace(Tensor input) /// /// The to take the base 10 logarithm of. public static Tensor Log10(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10); + Tensor output = Tensor.Create(input.Lengths); + Log10(input, output); + return output; } /// - /// Takes the base 10 logarithm of each element of the in place. + /// Takes the base 10 logarithm of each element of the and returns a new with the result. /// - /// The to take the base 10 logarithm of. - public static Tensor Log10InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the base 10 logarithm of. + /// + public static ref readonly TensorSpan Log10(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Log10); } #endregion @@ -2290,19 +3181,22 @@ public static Tensor Log10InPlace(Tensor input) /// /// The to take the base 10 logarithm of. public static Tensor Log10P1(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10P1); + Tensor output = Tensor.Create(input.Lengths); + Log10P1(input, output); + return output; } /// - /// Takes the base 10 logarithm plus 1 of each element of the in place. + /// Takes the base 10 logarithm plus 1 of each element of the and returns a new with the result. /// - /// The to take the base 10 logarithm of. - public static Tensor Log10P1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the base 10 logarithm of. + /// + public static ref readonly TensorSpan Log10P1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10P1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Log10P1); } #endregion @@ -2312,21 +3206,23 @@ public static Tensor Log10P1InPlace(Tensor input) /// /// The to take the base 2 logarithm of. public static Tensor Log2(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2); + Tensor output = Tensor.Create(input.Lengths); + Log2(input, output); + return output; } /// - /// Takes the base 2 logarithm of each element of the in place. + /// Takes the base 2 logarithm of each element of the and returns a new with the result. /// - /// The to take the base 2 logarithm of. - public static Tensor Log2InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the base 2 logarithm of. + /// + public static ref readonly TensorSpan Log2(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Log2); } - #endregion #region Log2P1 @@ -2335,19 +3231,22 @@ public static Tensor Log2InPlace(Tensor input) /// /// The to take the base 2 logarithm of. public static Tensor Log2P1(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2P1); + Tensor output = Tensor.Create(input.Lengths); + Log2P1(input, output); + return output; } /// - /// Takes the base 2 logarithm plus 1 of each element of the in place. + /// Takes the base 2 logarithm plus 1 of each element of the and returns a new with the result. /// - /// The to take the base 2 logarithm of. - public static Tensor Log2P1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the base 2 logarithm of. + /// + public static ref readonly TensorSpan Log2P1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2P1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Log2P1); } #endregion @@ -2357,19 +3256,22 @@ public static Tensor Log2P1InPlace(Tensor input) /// /// The to take the natural logarithm of. public static Tensor LogP1(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LogP1); + Tensor output = Tensor.Create(input.Lengths); + LogP1(input, output); + return output; } /// - /// Takes the natural logarithm plus 1 of each element of the in place. + /// Takes the natural logarithm plus 1 of each element of the and returns a new with the result. /// - /// The to take the natural logarithm of. - public static Tensor LogP1InPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions + /// The to take the natural logarithm of. + /// + public static ref readonly TensorSpan LogP1(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ILogarithmicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LogP1, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.LogP1); } #endregion @@ -2377,7 +3279,15 @@ public static Tensor LogP1InPlace(Tensor input) /// Searches for the largest number in the specified tensor. /// The input .. public static T Max(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return Max((ReadOnlyTensorSpan)input); + } + + /// Searches for the largest number in the specified tensor. + /// The input .. + public static T Max(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Max); } @@ -2387,7 +3297,15 @@ public static T Max(Tensor input) /// Searches for the number with the largest magnitude in the specified tensor. /// The input .. public static T MaxMagnitude(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return MaxMagnitude((ReadOnlyTensorSpan)input); + } + + /// Searches for the number with the largest magnitude in the specified tensor. + /// The input .. + public static T MaxMagnitude(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MaxMagnitude); } @@ -2397,7 +3315,15 @@ public static T MaxMagnitude(Tensor input) /// Searches for the largest number in the specified tensor. /// The input .. public static T MaxNumber(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return MaxNumber((ReadOnlyTensorSpan)input); + } + + /// Searches for the largest number in the specified tensor. + /// The input .. + public static T MaxNumber(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MaxNumber); } @@ -2407,7 +3333,15 @@ public static T MaxNumber(Tensor input) /// Searches for the smallest number in the specified tensor. /// The input . public static T Min(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return Min((ReadOnlyTensorSpan)input); + } + + /// Searches for the smallest number in the specified tensor. + /// The input . + public static T Min(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Min); } @@ -2417,7 +3351,15 @@ public static T Min(Tensor input) /// Searches for the number with the smallest magnitude in the specified tensor. /// The input . public static T MinMagnitude(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return MinMagnitude((ReadOnlyTensorSpan)input); + } + + /// Searches for the number with the smallest magnitude in the specified tensor. + /// The input . + public static T MinMagnitude(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MinMagnitude); } @@ -2427,7 +3369,15 @@ public static T MinMagnitude(Tensor input) /// Searches for the smallest number in the specified tensor. /// The input .. public static T MinNumber(Tensor input) - where T : IEquatable, IEqualityOperators, INumber + where T : INumber + { + return MinNumber((ReadOnlyTensorSpan)input); + } + + /// Searches for the smallest number in the specified tensor. + /// The input .. + public static T MinNumber(scoped in ReadOnlyTensorSpan input) + where T : INumber { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MinNumber); } @@ -2440,52 +3390,62 @@ public static T MinNumber(Tensor input) /// Input /// value to multiply by. public static Tensor Multiply(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + where T : IMultiplyOperators, IMultiplicativeIdentity { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Multiply(span, val, ospan); + Tensor output = Tensor.Create(input.Lengths, input.IsPinned); + Multiply((ReadOnlyTensorSpan)input, val, output); return output; } /// - /// Multiplies each element of with in place. + /// Multiplies each element of with and returns a new with the result. + /// If the shapes are not the same they are broadcast to the smallest compatible shape. /// - /// Input - /// value to multiply by. - public static Tensor MultiplyInPlace(Tensor input, T val) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + /// Left for multiplication. + /// Right for multiplication. + public static Tensor Multiply(Tensor left, Tensor right) + where T : IMultiplyOperators, IMultiplicativeIdentity { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Multiply(span, val, ospan); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Multiply((ReadOnlyTensorSpan)left, right, output); return output; } /// - /// Multiplies each element of with and returns a new with the result. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. + /// Multiplies each element of with and returns a new with the result. /// - /// Left for multiplication. - /// Right for multiplication. - public static Tensor Multiply(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + /// Input + /// value to multiply by. + /// + public static ref readonly TensorSpan Multiply(scoped in ReadOnlyTensorSpan input, T val, in TensorSpan destination) + where T : IMultiplyOperators, IMultiplicativeIdentity { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Multiply); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + TensorPrimitives.Multiply(span, val, ospan); + return ref destination; } /// - /// Multiplies each element of with in place. + /// Multiplies each element of with and returns a new with the result. /// If the shapes are not the same they are broadcast to the smallest compatible shape. /// - /// Left for multiplication. - /// Right for multiplication. - public static Tensor MultiplyInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity + /// Left for multiplication. + /// Right for multiplication. + /// + public static ref readonly TensorSpan Multiply(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IMultiplyOperators, IMultiplicativeIdentity { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Multiply, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Multiply); } #endregion @@ -2493,17 +3453,20 @@ public static Tensor MultiplyInPlace(Tensor left, Tensor right) /// Computes the element-wise negation of each number in the specified tensor. /// The public static Tensor Negate(Tensor input) - where T : IEquatable, IEqualityOperators, IUnaryNegationOperators + where T : IUnaryNegationOperators { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Negate); + Tensor output = Tensor.Create(input.Lengths); + Negate(input, output); + return output; } /// Computes the element-wise negation of each number in the specified tensor. - /// The - public static Tensor NegateInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IUnaryNegationOperators + /// The + /// + public static ref readonly TensorSpan Negate(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IUnaryNegationOperators { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Negate, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Negate); } #endregion @@ -2513,9 +3476,21 @@ public static Tensor NegateInPlace(Tensor input) /// /// The to take the norm of. public static T Norm(Tensor input) - where T : IEquatable, IEqualityOperators, IRootFunctions + where T : IRootFunctions + { + return Norm((ReadOnlyTensorSpan)input); + } + + + /// + /// Takes the norm of the and returns the result. + /// + /// The to take the norm of. + public static T Norm(scoped in ReadOnlyTensorSpan input) + where T : IRootFunctions { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Norm); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + return TensorPrimitives.Norm(span); } #endregion @@ -2523,17 +3498,20 @@ public static T Norm(Tensor input) /// Computes the element-wise one's complement of numbers in the specified tensor. /// The public static Tensor OnesComplement(Tensor input) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + where T : IBitwiseOperators { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.OnesComplement); + Tensor output = Tensor.Create(input.Lengths); + OnesComplement(input, output); + return output; } /// Computes the element-wise one's complement of numbers in the specified tensor. - /// The - public static Tensor OnesComplementInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + /// The + /// + public static ref readonly TensorSpan OnesComplement(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IBitwiseOperators { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.OnesComplement, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.OnesComplement); } #endregion @@ -2541,17 +3519,20 @@ public static Tensor OnesComplementInPlace(Tensor input) /// Computes the element-wise population count of numbers in the specified tensor. /// The public static Tensor PopCount(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.PopCount); + Tensor output = Tensor.Create(input.Lengths); + PopCount(input, output); + return output; } /// Computes the element-wise population count of numbers in the specified tensor. - /// The - public static Tensor PopCountInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + /// The + /// + public static ref readonly TensorSpan PopCount(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.PopCount, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.PopCount); } #endregion @@ -2560,18 +3541,30 @@ public static Tensor PopCountInPlace(Tensor input) /// The input . /// The second input public static Tensor Pow(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IPowerFunctions + where T : IPowerFunctions { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Pow); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Pow(left, right, output); + return output; } /// Computes the element-wise power of a number in a specified tensor raised to a number in another specified tensors. - /// The input . - /// The second input - public static Tensor PowInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IPowerFunctions + /// The input . + /// The second input + /// + public static ref readonly TensorSpan Pow(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IPowerFunctions { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Pow, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Pow); } #endregion @@ -2579,7 +3572,15 @@ public static Tensor PowInPlace(Tensor left, Tensor right) /// Computes the product of all elements in the specified non-empty tensor of numbers. /// The input . public static T Product(Tensor input) - where T : IEquatable, IEqualityOperators, IMultiplicativeIdentity, IMultiplyOperators + where T : IMultiplicativeIdentity, IMultiplyOperators + { + return Product((ReadOnlyTensorSpan)input); + } + + /// Computes the product of all elements in the specified non-empty tensor of numbers. + /// The input . + public static T Product(scoped in ReadOnlyTensorSpan input) + where T : IMultiplicativeIdentity, IMultiplyOperators { return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Product); } @@ -2589,17 +3590,20 @@ public static T Product(Tensor input) /// Computes the element-wise conversion of each number of radians in the specified tensor to degrees. /// The input . public static Tensor RadiansToDegrees(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.RadiansToDegrees); + Tensor output = Tensor.Create(input.Lengths); + RadiansToDegrees(input, output); + return output; } /// Computes the element-wise conversion of each number of radians in the specified tensor to degrees. - /// The input . - public static Tensor RadiansToDegreesInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The input . + /// + public static ref readonly TensorSpan RadiansToDegrees(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.RadiansToDegrees, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.RadiansToDegrees); } #endregion @@ -2607,17 +3611,20 @@ public static Tensor RadiansToDegreesInPlace(Tensor input) /// Computes the element-wise reciprocal of numbers in the specified tensor. /// The input . public static Tensor Reciprocal(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Reciprocal); + Tensor output = Tensor.Create(input.Lengths); + Reciprocal(input, output); + return output; } /// Computes the element-wise reciprocal of numbers in the specified tensor. - /// The input . - public static Tensor ReciprocalInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// The input . + /// + public static ref readonly TensorSpan Reciprocal(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Reciprocal, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Reciprocal); } #endregion @@ -2625,17 +3632,20 @@ public static Tensor ReciprocalInPlace(Tensor input) /// Computes the element-wise rounding of the numbers in the specified tensor /// The input . public static Tensor Round(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Round); + Tensor output = Tensor.Create(input.Lengths); + Round(input, output); + return output; } /// Computes the element-wise rounding of the numbers in the specified tensor - /// The input . - public static Tensor RoundInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// The input . + /// + public static ref readonly TensorSpan Round(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Round, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Round); } #endregion @@ -2643,17 +3653,20 @@ public static Tensor RoundInPlace(Tensor input) /// Computes the element-wise sigmoid function on the specified non-empty tensor of numbers. /// The input . public static Tensor Sigmoid(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sigmoid); + Tensor output = Tensor.Create(input.Lengths); + Sigmoid(input, output); + return output; } /// Computes the element-wise sigmoid function on the specified non-empty tensor of numbers. - /// The input . - public static Tensor SigmoidInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The input . + /// + public static ref readonly TensorSpan Sigmoid(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sigmoid, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Sigmoid); } #endregion @@ -2663,19 +3676,22 @@ public static Tensor SigmoidInPlace(Tensor input) /// /// The to take the sin of. public static Tensor Sin(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sin); + Tensor output = Tensor.Create(input.Lengths); + Sin(input, output); + return output; } /// - /// Takes the sin of each element of the in place. + /// Takes the sin of each element of the and returns a new with the result. /// - /// The to take the sin of. - public static Tensor SinInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Sin(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sin, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Sin); } #endregion @@ -2683,17 +3699,20 @@ public static Tensor SinInPlace(Tensor input) /// Computes the element-wise hyperbolic sine of each radian angle in the specified tensor. /// The to take the sin of. public static Tensor Sinh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sinh); + Tensor output = Tensor.Create(input.Lengths); + Sinh(input, output); + return output; } /// Computes the element-wise hyperbolic sine of each radian angle in the specified tensor. - /// The to take the sin of. - public static Tensor SinhInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Sinh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sinh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Sinh); } #endregion @@ -2701,17 +3720,20 @@ public static Tensor SinhInPlace(Tensor input) /// Computes the element-wise sine of the value in the specified tensor that has been multiplied by Pi. /// The to take the sin of. public static Tensor SinPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SinPi); + Tensor output = Tensor.Create(input.Lengths); + SinPi(input, output); + return output; } /// Computes the element-wise sine of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static Tensor SinPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan SinPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SinPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.SinPi); } #endregion @@ -2719,17 +3741,20 @@ public static Tensor SinPiInPlace(Tensor input) /// Computes the softmax function over the specified non-empty tensor of numbers. /// The to take the sin of. public static Tensor SoftMax(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SoftMax); + Tensor output = Tensor.Create(input.Lengths); + SoftMax(input, output); + return output; } /// Computes the softmax function over the specified non-empty tensor of numbers. - /// The to take the sin of. - public static Tensor SoftMaxInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan SoftMax(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IExponentialFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SoftMax, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.SoftMax); } #endregion @@ -2739,19 +3764,22 @@ public static Tensor SoftMaxInPlace(Tensor input) /// /// The to take the square root of. public static Tensor Sqrt(Tensor input) - where T : IEquatable, IEqualityOperators, IRootFunctions + where T : IRootFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sqrt); + Tensor output = Tensor.Create(input.Lengths); + Sqrt(input, output); + return output; } /// - /// Takes the square root of each element of the in place. + /// Takes the square root of each element of the and returns a new with the result. /// - /// The to take the square root of. - public static Tensor SqrtInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IRootFunctions + /// The to take the square root of. + /// + public static ref readonly TensorSpan Sqrt(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IRootFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sqrt, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Sqrt); } #endregion @@ -2762,27 +3790,10 @@ public static Tensor SqrtInPlace(Tensor input) /// The . /// The to subtract. public static Tensor Subtract(Tensor input, T val) - where T : IEquatable, IEqualityOperators, ISubtractionOperators + where T : ISubtractionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Subtract(span, val, ospan); - return output; - } - - /// - /// Subtracts from each element of in place. - /// - /// The . - /// The to subtract. - public static Tensor SubtractInPlace(Tensor input, T val) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Subtract(span, val, ospan); + Subtract(input, val, output); return output; } @@ -2792,83 +3803,111 @@ public static Tensor SubtractInPlace(Tensor input, T val) /// The to be subtracted from. /// The of values to subtract. public static Tensor Subtract(T val, Tensor input) - where T : IEquatable, IEqualityOperators, ISubtractionOperators + where T : ISubtractionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Subtract(val, span, ospan); + Subtract(val, input, output); return output; } /// - /// Subtracts each element of from in place. + /// Subtracts each element of from and returns a new with the result. /// - /// The to be subtracted from. - /// The of values to subtract. - public static Tensor SubtractInPlace(T val, Tensor input) - where T : IEquatable, IEqualityOperators, ISubtractionOperators + /// The with values to be subtracted from. + /// The with values to subtract. + public static Tensor Subtract(Tensor left, Tensor right) + where T : ISubtractionOperators { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - TensorPrimitives.Subtract(val, span, ospan); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Subtract(left, right, output); return output; } /// - /// Subtracts each element of from and returns a new with the result. + /// Subtracts from each element of and returns a new with the result. /// - /// The with values to be subtracted from. - /// The with values to subtract. - public static Tensor Subtract(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Subtract); + /// The with values to be subtracted from. + /// The value to subtract. + /// + public static ref readonly TensorSpan Subtract(scoped in ReadOnlyTensorSpan input, T val, in TensorSpan destination) + where T : ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + TensorPrimitives.Subtract(span, val, ospan); + return ref destination; } /// - /// Subtracts each element of from in place. + /// Subtracts each element of from and returns a new with the result. /// - /// The with values to be subtracted from. - /// The with values to subtract. - public static Tensor SubtractInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, ISubtractionOperators + /// The value to be subtracted from. + /// The values to subtract. + /// + public static ref readonly TensorSpan Subtract(T val, scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ISubtractionOperators + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + TensorPrimitives.Subtract(val, span, ospan); + return ref destination; + } + + /// + /// Subtracts each element of from and returns a new with the result. + /// + /// The of values to be subtracted from. + /// The of values to subtract. + /// + public static ref readonly TensorSpan Subtract(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : ISubtractionOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Subtract, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Subtract); } #endregion #region Sum - - /// - /// Sums all the elements of the and returns the result. - /// - /// The to sum. public static T Sum(Tensor input) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity + where T : IAdditionOperators, IAdditiveIdentity { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - return TensorPrimitives.Sum(span); + return Sum((ReadOnlyTensorSpan)input); } + public static T Sum(scoped in ReadOnlyTensorSpan input) + where T : IAdditionOperators, IAdditiveIdentity + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + return TensorPrimitives.Sum(span); + } #endregion #region Tan /// Computes the element-wise tangent of the value in the specified tensor. /// The to take the sin of. public static Tensor Tan(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tan); + Tensor output = Tensor.Create(input.Lengths); + Tan(input, output); + return output; } /// Computes the element-wise tangent of the value in the specified tensor. - /// The to take the sin of. - public static Tensor TanInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Tan(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tan, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Tan); } #endregion @@ -2876,17 +3915,20 @@ public static Tensor TanInPlace(Tensor input) /// Computes the element-wise hyperbolic tangent of each radian angle in the specified tensor. /// The to take the sin of. public static Tensor Tanh(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tanh); + Tensor output = Tensor.Create(input.Lengths); + Tanh(input, output); + return output; } /// Computes the element-wise hyperbolic tangent of each radian angle in the specified tensor. - /// The to take the sin of. - public static Tensor TanhInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan Tanh(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IHyperbolicFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tanh, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Tanh); } #endregion @@ -2894,17 +3936,20 @@ public static Tensor TanhInPlace(Tensor input) /// Computes the element-wise tangent of the value in the specified tensor that has been multiplied by Pi. /// The to take the sin of. public static Tensor TanPi(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TanPi); + Tensor output = Tensor.Create(input.Lengths); + TanPi(input, output); + return output; } /// Computes the element-wise tangent of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static Tensor TanPiInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions + /// The to take the sin of. + /// + public static ref readonly TensorSpan TanPi(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : ITrigonometricFunctions { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TanPi, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.TanPi); } #endregion @@ -2912,17 +3957,20 @@ public static Tensor TanPiInPlace(Tensor input) /// Computes the element-wise trailing zero count of numbers in the specified tensor. /// The input . public static Tensor TrailingZeroCount(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TrailingZeroCount); + Tensor output = Tensor.Create(input.Lengths); + TrailingZeroCount(input, output); + return output; } /// Computes the element-wise trailing zero count of numbers in the specified tensor. - /// The input . - public static Tensor TrailingZeroCountInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IBinaryInteger + /// The input . + /// + public static ref readonly TensorSpan TrailingZeroCount(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IBinaryInteger { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TrailingZeroCount, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.TrailingZeroCount); } #endregion @@ -2930,17 +3978,20 @@ public static Tensor TrailingZeroCountInPlace(Tensor input) /// Computes the element-wise truncation of numbers in the specified tensor. /// The input . public static Tensor Truncate(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Truncate); + Tensor output = Tensor.Create(input.Lengths); + Truncate(input, output); + return output; } /// Computes the element-wise truncation of numbers in the specified tensor. - /// The input . - public static Tensor TruncateInPlace(Tensor input) - where T : IEquatable, IEqualityOperators, IFloatingPoint + /// The input . + /// + public static ref readonly TensorSpan Truncate(scoped in ReadOnlyTensorSpan input, in TensorSpan destination) + where T : IFloatingPoint { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Truncate, true); + return ref TensorPrimitivesHelperSpanInSpanOut(input, destination, TensorPrimitives.Truncate); } #endregion @@ -2949,225 +4000,232 @@ public static Tensor TruncateInPlace(Tensor input) /// The left . /// The right . public static Tensor Xor(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Xor); + Tensor output; + if (left.Lengths.SequenceEqual(right.Lengths)) + { + output = Tensor.Create(left.Lengths); + } + else + { + output = Tensor.Create(GetSmallestBroadcastableLengths(left.Lengths, right.Lengths)); + } + + Xor(left, right, output); + return output; } /// Computes the element-wise XOR of numbers in the specified tensors. - /// The left . - /// The right . - public static Tensor XorInPlace(Tensor left, Tensor right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators + /// The left . + /// The right . + /// + public static ref readonly TensorSpan Xor(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination) + where T : IBitwiseOperators { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Xor, true); + return ref TensorPrimitivesHelperTwoSpanInSpanOut(left, right, destination, TensorPrimitives.Xor); } #endregion + public static nint[] GetSmallestBroadcastableLengths(ReadOnlySpan shape1, ReadOnlySpan shape2) + { + if (!TensorHelpers.IsBroadcastableTo(shape1, shape2)) + throw new Exception("Lengths are not broadcast compatible"); + + nint[] intermediateShape = TensorHelpers.GetIntermediateShape(shape1, shape2.Length); + for (int i = 1; i <= shape1.Length; i++) + { + intermediateShape[^i] = Math.Max(intermediateShape[^i], shape1[^i]); + } + for (int i = 1; i <= shape2.Length; i++) + { + intermediateShape[^i] = Math.Max(intermediateShape[^i], shape2[^i]); + } + + return intermediateShape; + } + #region TensorPrimitivesHelpers - private delegate void PerformCalculationTFromSpanInTToSpanOut(ReadOnlySpan input, Span output) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase; + private delegate void PerformCalculationSpanInSpanOut(ReadOnlySpan input, Span output); - private delegate void PerformCalculationSpanInTInSpanOut(ReadOnlySpan input, T value, Span output) - where T : IEquatable, IEqualityOperators; + private delegate void PerformCalculationSpanInTInSpanOut(ReadOnlySpan input, T value, Span output); - private delegate void PerformCalculationSpanInSpanOut(ReadOnlySpan input, Span output) - where T : IEquatable, IEqualityOperators; + private delegate void PerformCalculationTwoSpanInSpanOut(ReadOnlySpan input, ReadOnlySpan inputTwo, Span output); - private delegate void PerformCalculationSpanInIntSpanOut(ReadOnlySpan input, Span output) - where T : IEquatable, IEqualityOperators; + private delegate void PerformCalculationTFromSpanInTToSpanOut(ReadOnlySpan input, Span output) + where TFrom : INumberBase + where TTo : INumberBase; - private delegate T PerformCalculationTwoSpanInTOut(ReadOnlySpan input, ReadOnlySpan inputTwo) - where T : IEquatable, IEqualityOperators; + private delegate T PerformCalculationTwoSpanInTOut(ReadOnlySpan input, ReadOnlySpan inputTwo); - private delegate T PerformCalculationSpanInTOut(ReadOnlySpan input) - where T : IEquatable, IEqualityOperators; + private delegate void PerformCalculationSpanInIntSpanOut(ReadOnlySpan input, Span output); - private delegate void PerformCalculationTwoSpanInSpanOut(ReadOnlySpan input, ReadOnlySpan inputTwo, Span output) - where T : IEquatable, IEqualityOperators; + private delegate T PerformCalculationSpanInTOut(ReadOnlySpan input); - private static Tensor TensorPrimitivesHelperSpanInTInSpanOut(Tensor input, T value, PerformCalculationSpanInTInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators + private static T TensorPrimitivesHelperSpanInTOut(scoped in ReadOnlyTensorSpan input, PerformCalculationSpanInTOut performCalculation) { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = inPlace ? input : Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - performCalculation(span, value, ospan); - return output; + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + return performCalculation(span); } - private static Tensor TensorPrimitivesHelperSpanInIntSpanOut(Tensor input, PerformCalculationSpanInIntSpanOut performCalculation) - where T : IEquatable, IEqualityOperators + private static ref readonly TensorSpan TensorPrimitivesHelperSpanInIntSpanOut(scoped in ReadOnlyTensorSpan input, in TensorSpan destination, PerformCalculationSpanInIntSpanOut performCalculation) { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - performCalculation(span, ospan); - return output; + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + Span data = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination._flattenedLength); + performCalculation(span, data); + return ref destination; } - private static Tensor TensorPrimitivesHelperSpanInSpanOut(Tensor input, PerformCalculationSpanInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators + private static T TensorPrimitivesHelperTwoSpanInTOut(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, PerformCalculationTwoSpanInTOut performCalculation) { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = inPlace ? input : Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + // If sizes are the same. + if (left.Lengths.SequenceEqual(right.Lengths)) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); + return performCalculation(span, rspan); + } + // Broadcasting needs to happen. + else + { + // Have a couple different possible cases here. + // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) + // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) + // Because we are returning a single T though we need to actual realize the broadcasts at this point to perform the calculations. + + nint[] newLengths = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); + nint newLength = TensorSpanHelpers.CalculateTotalLength(newLengths); + TensorSpan broadcastedLeft = new TensorSpan(new T[newLength], newLengths, ReadOnlySpan.Empty); + TensorSpan broadcastedRight = new TensorSpan(new T[newLength], newLengths, ReadOnlySpan.Empty); + BroadcastTo(left, broadcastedLeft); + BroadcastTo(right, broadcastedRight); + + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref broadcastedLeft._reference, (int)broadcastedLeft.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref broadcastedRight._reference, (int)broadcastedRight.FlattenedLength); + return performCalculation(span, rspan); + } + } + + private static ref readonly TensorSpan TensorPrimitivesHelperSpanInSpanOut(scoped in ReadOnlyTensorSpan input, in TensorSpan destination, PerformCalculationSpanInSpanOut performCalculation) + { + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); performCalculation(span, ospan); - return output; + return ref destination; } - private static T TensorPrimitivesHelperSpanInTOut(Tensor input, PerformCalculationSpanInTOut performCalculation) - where T : IEquatable, IEqualityOperators + private static ref readonly TensorSpan TensorPrimitivesHelperSpanInTInSpanOut(scoped in ReadOnlyTensorSpan input, T value, in TensorSpan destination, PerformCalculationSpanInTInSpanOut performCalculation) { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - return performCalculation(span); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); + performCalculation(span, value, ospan); + return ref destination; } - private static Tensor TensorPrimitivesHelperTFromSpanInTToSpanOut(Tensor input, PerformCalculationTFromSpanInTToSpanOut performCalculation) + private static ref readonly TensorSpan TensorPrimitivesHelperTFromSpanInTToSpanOut(scoped in ReadOnlyTensorSpan input, in TensorSpan destination, PerformCalculationTFromSpanInTToSpanOut performCalculation) where TFrom : IEquatable, IEqualityOperators, INumberBase where TTo : INumberBase { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._values[0], (int)input._flattenedLength); - Tensor output = Create(input.Lengths, input.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination._flattenedLength); performCalculation(span, ospan); - return output; + return ref destination; } - private static Tensor TensorPrimitivesHelperTwoSpanInSpanOut(Tensor left, Tensor right, PerformCalculationTwoSpanInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators + private static ref readonly TensorSpan TensorPrimitivesHelperTwoSpanInSpanOut(scoped in ReadOnlyTensorSpan left, scoped in ReadOnlyTensorSpan right, in TensorSpan destination, PerformCalculationTwoSpanInSpanOut performCalculation) { - if (inPlace && !left.Lengths.SequenceEqual(right.Lengths)) - ThrowHelper.ThrowArgument_InPlaceInvalidShape(); - - Tensor output; - if (inPlace) - { - - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._values[0], (int)left._flattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._values[0], (int)right._flattenedLength); - output = left; - Span ospan = MemoryMarshal.CreateSpan(ref output._values[0], (int)output._flattenedLength); - performCalculation(span, rspan, ospan); - } - // If not in place but sizes are the same. - else if (left.Lengths.SequenceEqual(right.Lengths)) + // If sizes are the same. + if (left.Lengths.SequenceEqual(right.Lengths)) { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left.AsTensorSpan()._reference, (int)left.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right.AsTensorSpan()._reference, (int)right.FlattenedLength); - output = Create(left.Lengths, left.IsPinned); - Span ospan = MemoryMarshal.CreateSpan(ref output.AsTensorSpan()._reference, (int)output.FlattenedLength); + ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); + ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); + Span ospan = MemoryMarshal.CreateSpan(ref destination._reference, (int)destination.FlattenedLength); performCalculation(span, rspan, ospan); - return output; + return ref destination; } - // Not in place and broadcasting needs to happen. + // Broadcasting needs to happen. else { // Have a couple different possible cases here. // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); + nint[] newSize = Tensor.GetSmallestBroadcastableLengths(left.Lengths, right.Lengths); - var broadcastedLeft = Tensor.BroadcastTo(left, newSize); - var broadcastedRight = Tensor.BroadcastTo(right, newSize); + ReadOnlyTensorSpan broadcastedLeft = Tensor.LazyBroadcast(left, newSize); + ReadOnlyTensorSpan broadcastedRight = Tensor.LazyBroadcast(right, newSize); + if (!destination.Lengths.SequenceEqual(newSize)) + ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); - output = Create(newSize, left.IsPinned); nint rowLength = newSize[^1]; Span ospan; - Span ispan; + ReadOnlySpan ispan; Span buffer = new T[rowLength]; - scoped Span curIndexes; - nint[]? curIndexesArray; - if (newSize.Length> 6) + scoped Span curIndex; + nint[]? curIndexArray; + if (newSize.Length > 6) { - curIndexesArray = ArrayPool.Shared.Rent(newSize.Length); - curIndexes = curIndexesArray; + curIndexArray = ArrayPool.Shared.Rent(newSize.Length); + curIndex = curIndexArray; } else { - curIndexesArray = null; - curIndexes = stackalloc nint[newSize.Length]; + curIndexArray = null; + curIndex = stackalloc nint[newSize.Length]; } int outputOffset = 0; + // ADD IN CASE WHERE NEITHER ARE ROW CONTIGUOUS // tensor not row contiguous if (broadcastedLeft.Strides[^1] == 0) { - while (outputOffset < output.FlattenedLength) + while (outputOffset < destination.FlattenedLength) { - ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); - buffer.Fill(broadcastedLeft[curIndexes]); - ispan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndexes], (int)rowLength); + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref destination._reference, outputOffset), (int)rowLength); + buffer.Fill(broadcastedLeft[curIndex]); + ispan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref broadcastedRight._reference, TensorSpanHelpers.ComputeLinearIndex(curIndex, broadcastedRight.Strides, broadcastedRight.Lengths)), (int)rowLength); performCalculation(buffer, ispan, ospan); outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); } } - // right now row contiguous + // right not row contiguous else if (broadcastedRight.Strides[^1] == 0) { - while (outputOffset < output.FlattenedLength) + while (outputOffset < destination.FlattenedLength) { - ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); - buffer.Fill(broadcastedRight[curIndexes]); - ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndexes], (int)rowLength); + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref destination._reference, outputOffset), (int)rowLength); + buffer.Fill(broadcastedRight[curIndex]); + ispan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref broadcastedLeft._reference, TensorSpanHelpers.ComputeLinearIndex(curIndex, broadcastedLeft.Strides, broadcastedLeft.Lengths)), (int)rowLength); performCalculation(ispan, buffer, ospan); outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); } } // both row contiguous else { Span rspan; - while (outputOffset < output.FlattenedLength) + while (outputOffset < destination.FlattenedLength) { - ospan = MemoryMarshal.CreateSpan(ref output._values[outputOffset], (int)rowLength); - ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndexes], (int)rowLength); - rspan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndexes], (int)rowLength); + ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref destination._reference, outputOffset), (int)rowLength); + ispan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref broadcastedLeft._reference, TensorSpanHelpers.ComputeLinearIndex(curIndex, broadcastedLeft.Strides, broadcastedLeft.Lengths)), (int)rowLength); + rspan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref broadcastedRight._reference, TensorSpanHelpers.ComputeLinearIndex(curIndex, broadcastedRight.Strides, broadcastedRight.Lengths)), (int)rowLength); performCalculation(ispan, rspan, ospan); outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndexes, broadcastedLeft.Lengths); + TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); } } - if (curIndexesArray != null) - ArrayPool.Shared.Return(curIndexesArray); + if (curIndexArray != null) + ArrayPool.Shared.Return(curIndexArray); } - - return output; + return ref destination; } - private static T TensorPrimitivesHelperTwoSpanInTOut(Tensor left, Tensor right, PerformCalculationTwoSpanInTOut performCalculation) - where T : IEquatable, IEqualityOperators - { - // If not in place but sizes are the same. - if (left.Lengths.SequenceEqual(right.Lengths)) - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left.AsTensorSpan()._reference, (int)left.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right.AsTensorSpan()._reference, (int)right.FlattenedLength); - return performCalculation(span, rspan); - } - // Not in place and broadcasting needs to happen. - else - { - // Have a couple different possible cases here. - // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) - // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) - // Because we are returning a single T though we need to actual realize the broadcasts at this point to perform the calculations. - - var broadcastedLeft = Tensor.Broadcast(left, right); - var broadcastedRight = Tensor.Broadcast(right, left); - - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref broadcastedLeft.AsTensorSpan()._reference, (int)broadcastedLeft.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref broadcastedRight.AsTensorSpan()._reference, (int)broadcastedRight.FlattenedLength); - return performCalculation(span, rspan); - } - } #endregion + #endregion } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs index 0fd46eb8d58f55..15428fb9ab280d 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorHelpers.cs @@ -15,9 +15,9 @@ internal static class TensorHelpers /// /// /// How many boolean values are true. - public static nint CountTrueElements(Tensor filter) + public static nint CountTrueElements(scoped in ReadOnlyTensorSpan filter) { - Span filterSpan = MemoryMarshal.CreateSpan(ref filter._values[0], (int)filter._flattenedLength); + Span filterSpan = MemoryMarshal.CreateSpan(ref filter._reference, (int)filter._flattenedLength); nint count = 0; for (int i = 0; i < filterSpan.Length; i++) { @@ -28,31 +28,31 @@ public static nint CountTrueElements(Tensor filter) return count; } - internal static bool AreShapesBroadcastCompatible(Tensor tensor1, Tensor tensor2) - where T : IEquatable, IEqualityOperators => AreShapesBroadcastCompatible(tensor1.Lengths, tensor2.Lengths); + internal static bool IsBroadcastableTo(Tensor tensor1, Tensor tensor2) + where T : IEquatable, IEqualityOperators => IsBroadcastableTo(tensor1.Lengths, tensor2.Lengths); - internal static bool AreShapesBroadcastCompatible(ReadOnlySpan shape1, ReadOnlySpan shape2) + internal static bool IsBroadcastableTo(ReadOnlySpan lengths1, ReadOnlySpan lengths2) { - int shape1Index = shape1.Length - 1; - int shape2Index = shape2.Length - 1; + int lengths1Index = lengths1.Length - 1; + int lengths2Index = lengths2.Length - 1; bool areCompatible = true; nint s1; nint s2; - while (shape1Index >= 0 || shape2Index >= 0) + while (lengths1Index >= 0 || lengths2Index >= 0) { // if a dimension is missing in one of the shapes, it is considered to be 1 - if (shape1Index < 0) + if (lengths1Index < 0) s1 = 1; else - s1 = shape1[shape1Index--]; + s1 = lengths1[lengths1Index--]; - if (shape2Index < 0) + if (lengths2Index < 0) s2 = 1; else - s2 = shape2[shape2Index--]; + s2 = lengths2[lengths2Index--]; if (s1 == s2 || (s1 == 1 && s2 != 1) || (s2 == 1 && s1 != 1)) { } else @@ -65,24 +65,6 @@ internal static bool AreShapesBroadcastCompatible(ReadOnlySpan shape1, Rea return areCompatible; } - internal static nint[] GetSmallestBroadcastableSize(ReadOnlySpan shape1, ReadOnlySpan shape2) - { - if (!AreShapesBroadcastCompatible(shape1, shape2)) - throw new Exception("Shapes are not broadcast compatible"); - - nint[] intermediateShape = GetIntermediateShape(shape1, shape2.Length); - for (int i = 1; i <= shape1.Length; i++) - { - intermediateShape[^i] = Math.Max(intermediateShape[^i], shape1[^i]); - } - for (int i = 1; i <= shape2.Length; i++) - { - intermediateShape[^i] = Math.Max(intermediateShape[^i], shape2[^i]); - } - - return intermediateShape; - } - internal static nint[] GetIntermediateShape(ReadOnlySpan shape1, int shape2Length) { int shape1Index = shape1.Length - 1; @@ -102,11 +84,13 @@ internal static nint[] GetIntermediateShape(ReadOnlySpan shape1, int shape } internal static bool IsUnderlyingStorageSameSize(Tensor tensor1, Tensor tensor2) - where T : IEquatable, IEqualityOperators => tensor1.Lengths.Length == tensor2.Lengths.Length; + => tensor1.Lengths.Length == tensor2.Lengths.Length; - internal static bool AreShapesTheSame(Tensor tensor1, Tensor tensor2) - where T : IEquatable, IEqualityOperators => tensor1._lengths.SequenceEqual(tensor2._lengths); + internal static bool AreLengthsTheSame(ReadOnlyTensorSpan tensor1, ReadOnlyTensorSpan tensor2) + => tensor1._lengths.SequenceEqual(tensor2._lengths); + internal static bool AreLengthsTheSame(ReadOnlySpan lengths1, ReadOnlySpan lengths2) + => lengths1.SequenceEqual(lengths2); internal static void PermuteIndices(Span indices, Span permutedIndices, ReadOnlySpan permutation) { diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs deleted file mode 100644 index 65a0f697d9c045..00000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanExtensions.cs +++ /dev/null @@ -1,2434 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; - -namespace System.Numerics.Tensors -{ - public static class TensorSpan - { - #region SequenceEqual - /// - /// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T). - /// - public static bool SequenceEqual(this ReadOnlyTensorSpan span, in ReadOnlyTensorSpan other) where T : IEquatable? - { - return span.FlattenedLength == other.FlattenedLength - && MemoryMarshal.CreateReadOnlySpan(in span.GetPinnableReference(), (int)span.FlattenedLength).SequenceEqual(MemoryMarshal.CreateReadOnlySpan(in other.GetPinnableReference(), (int)other.FlattenedLength)); - } - - /// - /// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T). - /// - public static bool SequenceEqual(this TensorSpan span, in TensorSpan other) where T : IEquatable? - { - return ((ReadOnlyTensorSpan)span).SequenceEqual((ReadOnlyTensorSpan)other); - } - - /// - /// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T). - /// - public static bool SequenceEqual(this TensorSpan span, in ReadOnlyTensorSpan other) where T : IEquatable? - { - return ((ReadOnlyTensorSpan)span).SequenceEqual(other); - } - #endregion - - #region AsTensorSpan - /// - /// Extension method to more easily create a TensorSpan from an array. - /// - /// The type of the elements in the array - /// The with the data - /// The shape for the - /// - public static TensorSpan AsTensorSpan(this T[]? array, params ReadOnlySpan shape) => new(array, 0, shape, default); - #endregion - - #region ToString - // REVIEW: WHAT SHOULD WE NAME THIS? WHERE DO WE WANT IT TO LIVE? - /// - /// Creates a representation of the ."/> - /// - /// The you want to represent as a string. - /// Maximum Length of each dimension - /// A representation of the - public static string ToString(this TensorSpan span, params ReadOnlySpan maximumLengths) => ((ReadOnlyTensorSpan)span).ToString(maximumLengths); - - /// - /// Creates a representation of the ."/> - /// - /// - /// The you want to represent as a string. - /// Maximum Length of each dimension - public static string ToString(this ReadOnlyTensorSpan span, params ReadOnlySpan maximumLengths) - { - var sb = new StringBuilder(); - scoped Span curIndexes; - nint[]? curIndexesArray; - if (span.Rank > 6) - { - curIndexesArray = ArrayPool.Shared.Rent(span.Rank); - curIndexes = curIndexesArray; - } - else - { - curIndexesArray = null; - curIndexes = stackalloc nint[span.Rank]; - } - - nint copiedValues = 0; - - T[] values = new T[span.Lengths[span.Rank - 1]]; - while (copiedValues < span._flattenedLength) - { - var sp = new ReadOnlyTensorSpan(ref Unsafe.Add(ref span._reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, span.Strides, span.Lengths)), [span.Lengths[span.Rank - 1]], [1], span.Lengths[span.Rank - 1]); - sb.Append('{'); - sp.FlattenTo(values); - sb.Append(string.Join(",", values)); - sb.AppendLine("}"); - - TensorSpanHelpers.AdjustIndexes(span.Rank - 2, 1, curIndexes, span._lengths); - copiedValues += span.Lengths[span.Rank - 1]; - } - - if (curIndexesArray != null) - ArrayPool.Shared.Return(curIndexesArray); - - return sb.ToString(); - } - #endregion - - #region Broadcast - /// - /// Broadcast the data from to the smallest broadcastable shape compatible with . Creates a new and allocates new memory. - /// - /// Input . - /// Other to make shapes broadcastable. - public static TensorSpan Broadcast(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators - { - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - - TensorSpan intermediate = BroadcastTo(left, newSize); - T[] data = new T[intermediate.FlattenedLength]; - intermediate.FlattenTo(data); - return new TensorSpan(data, 0, intermediate.Lengths, []); - } - - /// - /// Broadcast the data from to the new shape . Creates a new and allocates new memory. - /// If the shape of the is not compatible with the new shape, an exception is thrown. - /// - /// Input . - /// of the desired new shape. - /// Thrown when the shapes are not broadcast compatible. - public static TensorSpan Broadcast(TensorSpan input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators - { - TensorSpan intermediate = BroadcastTo(input, shape); - T[] data = new T[intermediate.FlattenedLength]; - intermediate.FlattenTo(data); - return new TensorSpan(data, 0, intermediate.Lengths, []); - } - - // Lazy/non-copy broadcasting, internal only for now. - /// - /// Broadcast the data from to the new shape . Creates a new - /// but no memory is allocated. It manipulates the strides to achieve this affect. - /// If the shape of the is not compatible with the new shape, an exception is thrown. - /// - /// Input . - /// of the desired new shape. - /// Thrown when the shapes are not broadcast compatible. - internal static TensorSpan BroadcastTo(TensorSpan input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators - { - if (input.Lengths.SequenceEqual(shape)) - return new TensorSpan(ref input._reference, shape, input.Strides, input._memoryLength); - - if (!TensorHelpers.AreShapesBroadcastCompatible(input.Lengths, shape)) - ThrowHelper.ThrowArgument_ShapesNotBroadcastCompatible(); - - nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); - - if (newSize == input.FlattenedLength) - return Reshape(input, shape); - - nint[] intermediateShape = TensorHelpers.GetIntermediateShape(input.Lengths, shape.Length); - nint[] strides = new nint[shape.Length]; - - nint stride = 1; - - for (int i = strides.Length - 1; i >= 0; i--) - { - if ((intermediateShape[i] == 1 && shape[i] != 1) || (intermediateShape[i] == 1 && shape[i] == 1)) - strides[i] = 0; - else - { - strides[i] = stride; - stride *= intermediateShape[i]; - } - } - - TensorSpan output = new TensorSpan(ref input._reference, shape, strides, input._memoryLength); - - return output; - } - #endregion - - #region Reverse - /// - /// Reverse the order of elements in the along the given axis. The shape of the tensor is preserved, but the elements are reordered. - /// defaults to -1 when not provided, which reverses the entire span. - /// - /// Input . - /// Axis along which to reverse over. The default, -1, will reverse over all of the axes of the left span. - public static TensorSpan Reverse(TensorSpan input, nint axis = -1) - where T : IEquatable, IEqualityOperators - { - if (axis == -1) - { - nint index = input.FlattenedLength - 1; - Span span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T temp; - for (int i = 0; i <= input.FlattenedLength / 2; i++) - { - temp = span[(int)index]; - span[(int)index] = span[i]; - span[i] = temp; - } - } - else - { - T[] values = new T[input.FlattenedLength]; - - nint copyLength = 1; - for (nint i = axis; i < input.Lengths.Length; i++) - { - copyLength *= input.Lengths[(int)i]; - } - copyLength /= input.Lengths[(int)axis]; - - scoped Span oIndices; - nint[]? oIndicesArray; - scoped Span iIndices; - nint[]? iIndicesArray; - if (input.Rank > 6) - { - oIndicesArray = ArrayPool.Shared.Rent(input.Rank); - oIndices = oIndicesArray; - iIndicesArray = ArrayPool.Shared.Rent(input.Rank); - iIndices = iIndicesArray; - } - else - { - oIndicesArray = null; - oIndices = stackalloc nint[input.Rank]; - iIndicesArray = null; - iIndices = stackalloc nint[input.Rank]; - } - - iIndices[(int)axis] = input.Lengths[(int)axis] - 1; - nint copiedValues = 0; - TensorSpan islice = input.Slice(input.Lengths); - while (copiedValues < input.FlattenedLength) - { - TensorSpanHelpers.Memmove(ref Unsafe.Add(ref values, TensorSpanHelpers.ComputeLinearIndex(oIndices, input.Strides, input.Lengths)), ref Unsafe.Add(ref islice._reference, TensorSpanHelpers.ComputeLinearIndex(iIndices, islice.Strides, islice.Lengths)), copyLength); - TensorSpanHelpers.AdjustIndexes((int)axis, 1, oIndices, input.Lengths); - TensorSpanHelpers.AdjustIndexesDown((int)axis, 1, iIndices, input.Lengths); - copiedValues += copyLength; - } - TensorSpanHelpers.Memmove(ref input._reference, ref values[0], input.FlattenedLength); - - if (oIndicesArray != null && iIndicesArray != null) - { - ArrayPool.Shared.Return(oIndicesArray); - ArrayPool.Shared.Return(iIndicesArray); - } - } - - return input; - } - #endregion - - #region Reshape - /// - /// Reshapes the tensor to the specified . If one of the lengths is -1, it will be calculated automatically. - /// Does not change the length of the underlying memory nor does it allocate new memory. If the new shape is not compatible with the old shape, - /// an exception is thrown. - /// - /// you want to reshape. - /// with the new dimensions. - public static TensorSpan Reshape(this TensorSpan input, params ReadOnlySpan lengths) - where T : IEquatable, IEqualityOperators - { - nint[] arrLengths = lengths.ToArray(); - // Calculate wildcard info. - if (lengths.Contains(-1)) - { - if (lengths.Count(-1) > 1) - ThrowHelper.ThrowArgument_OnlyOneWildcard(); - nint tempTotal = input.FlattenedLength; - for (int i = 0; i < lengths.Length; i++) - { - if (lengths[i] != -1) - { - tempTotal /= lengths[i]; - } - } - arrLengths[lengths.IndexOf(-1)] = tempTotal; - - } - - nint tempLinear = TensorSpanHelpers.CalculateTotalLength(arrLengths); - if (tempLinear != input.FlattenedLength) - ThrowHelper.ThrowArgument_InvalidReshapeDimensions(); - nint[] strides = TensorSpanHelpers.CalculateStrides(arrLengths); - return new TensorSpan(ref input._reference, arrLengths, strides, input._memoryLength); - } - #endregion - - #region Resize - /// - /// Creates a new , allocates new managed memory, and copies the data from . If the final shape is smaller all data after - /// - /// Input . - /// of the desired new shape. - public static TensorSpan Resize(TensorSpan input, ReadOnlySpan shape) - where T : IEquatable, IEqualityOperators - { - nint newSize = TensorSpanHelpers.CalculateTotalLength(shape); - T[] values = new T[newSize]; - TensorSpan output = new TensorSpan(values, 0, shape, default); - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - if (newSize > input.FlattenedLength) - TensorSpanHelpers.Memmove(ospan, span, input.FlattenedLength); - else - TensorSpanHelpers.Memmove(ospan, span, newSize); - - return output; - } - #endregion - - #region Squeeze - // REVIEW: NAME? - /// - /// Removes axis of length one from the . defaults to -1 and will remove all axis with length of 1. - /// If is specified, it will only remove that axis and if it is not of length one it will throw an exception. - /// - /// The to remove axis of length 1. - /// The axis to remove. Defaults to -1 which removes all axis of length 1. - public static TensorSpan Squeeze(TensorSpan input, int axis = -1) - where T : IEquatable, IEqualityOperators - { - if (axis >= input.Rank) - ThrowHelper.ThrowArgument_AxisLargerThanRank(); - - nint[] lengths; - nint[] strides; - - List tempLengths = new List(); - if (axis == -1) - { - for (int i = 0; i < input.Lengths.Length; i++) - { - if (input.Lengths[i] != 1) - { - tempLengths.Add(input.Lengths[i]); - } - } - lengths = tempLengths.ToArray(); - strides = TensorSpanHelpers.CalculateStrides(lengths); - } - else - { - if (input.Lengths[axis] != 1) - { - ThrowHelper.ThrowArgument_InvalidSqueezeAxis(); - } - for (int i = 0; i < input.Lengths.Length; i++) - { - if (i != axis) - { - tempLengths.Add(input.Lengths[i]); - } - } - lengths = tempLengths.ToArray(); - strides = TensorSpanHelpers.CalculateStrides(lengths); - } - - return new TensorSpan(ref input._reference, lengths, strides, input._memoryLength); - } - #endregion - - #region Unsqueeze - // REVIEW: NAME? NUMPY CALLS THIS expand_dims. - /// - /// Insert a new axis of length 1 that will appear at the axis position. - /// - /// The to remove axis of length 1. - /// The axis to add. - public static TensorSpan Unsqueeze(TensorSpan input, int axis) - where T : IEquatable, IEqualityOperators - { - if (axis > input.Lengths.Length) - ThrowHelper.ThrowArgument_AxisLargerThanRank(); - if (axis < 0) - axis = input.Rank - axis; - - List tempLengths = input._lengths.ToArray().ToList(); - tempLengths.Insert(axis, 1); - nint[] lengths = tempLengths.ToArray(); - nint[] strides = TensorSpanHelpers.CalculateStrides(lengths); - return new TensorSpan(ref input._reference, lengths, strides, input._memoryLength); - } - #endregion - - #region StdDev - /// - /// Returns the standard deviation of the elements in the tensor. - /// - /// The to take the standard deviation of. - /// representing the standard deviation. - public static T StdDev(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity - - { - T mean = Mean(input); - Span span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - Span output = new T[input._flattenedLength].AsSpan(); - TensorPrimitives.Subtract(span, mean, output); - TensorPrimitives.Abs(output, output); - TensorPrimitives.Pow((ReadOnlySpan)output, T.CreateChecked(2), output); - T sum = TensorPrimitives.Sum((ReadOnlySpan)output); - return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); - } - - /// - /// Return the standard deviation of the elements in the tensor. Casts the return value to . - /// - /// The to take the standard deviation of. - /// representing the standard deviation. - public static TResult StdDev(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber, IFloatingPoint, IPowerFunctions, IAdditionOperators, IAdditiveIdentity - where TResult : IEquatable, IEqualityOperators, IFloatingPoint - - { - T mean = Mean(input); - Span span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - Span output = new T[input._flattenedLength].AsSpan(); - TensorPrimitives.Subtract(span, mean, output); - TensorPrimitives.Abs(output, output); - TensorPrimitives.Pow((ReadOnlySpan)output, T.CreateChecked(2), output); - T sum = TensorPrimitives.Sum((ReadOnlySpan)output); - return TResult.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); - } - - #endregion - - #region Mean - /// - /// Returns the mean of the elements in the tensor. - /// - /// The to take the mean of. - /// representing the mean. - public static T Mean(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - - { - T sum = Sum(input); - return T.CreateChecked(sum / T.CreateChecked(input.FlattenedLength)); - } - - /// - /// Return the mean of the elements in the tensor. Casts the return value to . - /// - /// The to take the mean of. - /// representing the mean. - public static TResult Mean(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - where TResult : IEquatable, IEqualityOperators, IFloatingPoint - - { - T sum = Sum(input); - return TResult.CreateChecked(TResult.CreateChecked(sum) / TResult.CreateChecked(input.FlattenedLength)); - } - - #endregion - - #region TensorPrimitives - #region Abs - /// - /// Takes the absolute value of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Abs(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumberBase - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Abs); - } - - /// - /// Takes the absolute of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AbsInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumberBase - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Abs, true); - } - #endregion - - #region Acos - /// - /// Takes the inverse cosine of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Acos(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acos); - } - - /// - /// Takes the inverse cosine of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AcosInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acos, true); - } - #endregion - - #region Acosh - /// - /// Takes the inverse hyperbolic cosine of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Acosh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acosh); - } - - /// - /// Takes the inverse hyperbolic cosine of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AcoshInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Acosh, true); - } - #endregion - - #region AcosPi - /// - /// Takes the inverse hyperbolic cosine divided by pi of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan AcosPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AcosPi); - } - - /// - /// Takes the inverse hyperbolic cosine divided by pi of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AcosPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AcosPi, true); - } - #endregion - - #region Add - /// - /// Adds each element of to each element of and returns a new with the result. - /// - /// The of values to add. - /// The second of values to add. - public static TensorSpan Add(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Add); - } - - /// - /// Adds each element of to each element of in place. - /// - /// The of values to add. - /// The second of values to add. - public static TensorSpan AddInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Add, true); - } - - /// - /// Adds to each element of and returns a new with the result. - /// - /// The of values to add. - /// The to add to each element of . - public static TensorSpan Add(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - return TensorPrimitivesHelperSpanInTInSpanOut(input, val, TensorPrimitives.Add); - } - - /// - /// Adds to each element of in place. - /// - /// The of values to add. - /// The to add to each element of . - public static TensorSpan AddInPlace(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - return TensorPrimitivesHelperSpanInTInSpanOut(input, val, TensorPrimitives.Add, true); - - } - #endregion - - #region Asin - /// - /// Takes the inverse sin of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Asin(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asin); - } - - /// - /// Takes the inverse sine each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AsinInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asin, true); - } - #endregion - - #region Asinh - /// - /// Takes the inverse hyperbolic sine of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Asinh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asinh); - } - - /// - /// Takes the inverse hyperbolic sine each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AsinhInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Asinh, true); - } - #endregion - - #region AsinPi - /// - /// Takes the inverse hyperbolic sine divided by pi of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan AsinPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AsinPi); - } - - /// - /// Takes the inverse hyperbolic sine divided by pi of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan AsinPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AsinPi, true); - } - #endregion - - #region Atan - /// - /// Takes the arc tangent of each element of the and returns a new with the result. - /// - /// The input - public static TensorSpan Atan(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atan); - } - - /// - /// Takes the arc tangent of each element of the in place. - /// - /// The input - public static TensorSpan AtanInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atan, true); - } - #endregion - - #region Atan2 - /// - /// Takes the arc tangent of the two input and returns a new with the result. - /// - /// The left . - /// The right . - public static TensorSpan Atan2(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2); - } - - /// - /// Takes the arc tangent of the two input in place. - /// - /// The left . - /// The right . - public static TensorSpan Atan2InPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2, true); - } - #endregion - - #region Atan2Pi - /// - /// Takes the arc tangent of the two input , divides each element by pi, and returns a new with the result. - /// - /// The left . - /// The right . - public static TensorSpan Atan2Pi(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2Pi); - } - - /// - /// Takes the arc tangent of the two input , divides each element by pi in place. - /// - /// The left . - /// The right . - public static TensorSpan Atan2PiInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Atan2Pi, true); - } - #endregion - - #region Atanh - /// - /// Takes the inverse hyperbolic tangent of each element of the and returns a new with the result. - /// - /// The input . - public static TensorSpan Atanh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atanh); - } - - /// - /// Takes the inverse hyperbolic tangent of each element of the in place. - /// - /// The input . - public static TensorSpan AtanhInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Atanh, true); - } - #endregion - - #region AtanPi - /// - /// Takes the inverse hyperbolic tangent divided by pi of each element of the and returns a new with the result. - /// - /// The input. - public static TensorSpan AtanPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AtanPi); - } - - /// - /// Takes the inverse hyperbolic tangent divided by pi of each element of the in place. - /// - /// The input. - public static TensorSpan AtanPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.AtanPi, true); - } - #endregion - - #region BitwiseAnd - /// - /// Computes the element-wise bitwise and of the two input and returns a new with the result. - /// - /// The left . - /// The right . - public static TensorSpan BitwiseAnd(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseAnd); - } - - /// - /// Computes the element-wise bitwise and of the two input in place. - /// - /// The left . - /// The right . - public static TensorSpan BitwiseAndInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseAnd, true); - } - #endregion - - #region BitwiseOr - /// - /// Computes the element-wise bitwise of of the two input and returns a new with the result. - /// - /// The left . - /// The right . - public static TensorSpan BitwiseOr(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseOr); - } - - /// - /// Computes the element-wise bitwise of of the two input in place. - /// - /// The left . - /// The right . - public static TensorSpan BitwiseOrInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.BitwiseOr, true); - } - #endregion - - #region CubeRoot - /// - /// Computes the element-wise cube root of the input and returns a new with the result. - /// - /// The left . - public static TensorSpan CubeRoot(TensorSpan input) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cbrt); - } - - /// - /// Computes the element-wise cube root of the input in place. - /// - /// The left . - public static TensorSpan CubeRootInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cbrt, true); - } - #endregion - - #region Ceiling - /// - /// Computes the element-wise ceiling of the input and returns a new with the result. - /// - /// The left . - public static TensorSpan Ceiling(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Ceiling); - } - - /// - /// Computes the element-wise ceiling of the input in place. - /// - /// The left . - public static TensorSpan CeilingInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Ceiling, true); - } - #endregion - - #region ConvertChecked - /// - /// Copies to a new converting each - /// value to a value. - /// - /// The input . - public static TensorSpan ConvertChecked(TensorSpan source) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase - { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertChecked); - } - #endregion - - #region ConvertSaturating - /// - /// Copies to a new converting each - /// value to a value. - /// - /// The input . - public static TensorSpan ConvertSaturating(TensorSpan source) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase - { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertSaturating); - } - #endregion - - #region ConvertTruncating - /// - /// Copies to a new converting each - /// value to a value. - /// - /// The input . - public static TensorSpan ConvertTruncating(TensorSpan source) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase - { - return TensorPrimitivesHelperTFromSpanInTToSpanOut(source, TensorPrimitives.ConvertTruncating); - } - #endregion - - #region CopySign - /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new tensor with the result. - /// - /// Input . - /// The number with the associated sign. - public static TensorSpan CopySign(TensorSpan input, T sign) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTInSpanOut(input, sign, TensorPrimitives.CopySign); - } - - /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors in place. - /// - /// Input . - /// The number with the associated sign. - public static TensorSpan CopySignInPlace(TensorSpan input, T sign) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTInSpanOut(input, sign, TensorPrimitives.CopySign, true); - } - - /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors and returns a new with the result. - /// - /// Input . - /// The with the associated signs. - public static TensorSpan CopySign(TensorSpan input, TensorSpan sign) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperTwoSpanInSpanOut(input, sign, TensorPrimitives.CopySign); - } - - /// - /// Computes the element-wise result of copying the sign from one number to another number in the specified tensors in place. - /// - /// Input . - /// The with the associated signs. - public static TensorSpan CopySignInPlace(TensorSpan input, TensorSpan sign) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperTwoSpanInSpanOut(input, sign, TensorPrimitives.CopySign, true); - } - #endregion - - #region Cos - /// - /// Takes the cosine of each element of the and returns a new with the result. - /// - /// The to take the cosine of. - public static TensorSpan Cos(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cos); - } - - /// - /// Takes the cosine of each element of the in place. - /// - /// The to take the cosine of. - public static TensorSpan CosInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cos, true); - } - #endregion - - #region Cosh - /// - /// Takes the hyperbolic cosine of each element of the and returns a new with the result. - /// - /// The to take the cosine of. - public static TensorSpan Cosh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cosh); - } - - /// - /// Takes the hyperbolic cosine of each element of the in place. - /// - /// The to take the cosine of. - public static TensorSpan CoshInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Cosh, true); - } - #endregion - - #region CosineSimilarity - /// - /// Compute cosine similarity between and . - /// - /// The first - /// The second - public static TensorSpan CosineSimilarity(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - if (left.Rank != 2) - ThrowHelper.ThrowArgument_2DTensorRequired(nameof(left)); - - if (right.Rank != 2) - ThrowHelper.ThrowArgument_2DTensorRequired(nameof(right)); - - if (left.Lengths[1] != right.Lengths[1]) - ThrowHelper.ThrowArgument_IncompatibleDimensions(left.Lengths[1], right.Lengths[1]); - - nint dim1 = left.Lengths[0]; - nint dim2 = right.Lengths[0]; - - T[] values = new T[dim1 * dim2]; - - scoped Span leftIndexes = stackalloc nint[2]; - scoped Span rightIndexes = stackalloc nint[2]; - - int outputOffset = 0; - - ReadOnlySpan lspan; - ReadOnlySpan rspan; - int rowLength = (int)left.Lengths[1]; - for (int i = 0; i < dim1; i++) - { - for (int j = 0; j < dim2; j++) - { - lspan = MemoryMarshal.CreateSpan(ref left[leftIndexes], rowLength); - rspan = MemoryMarshal.CreateSpan(ref right[rightIndexes], rowLength); - values[outputOffset++] = TensorPrimitives.CosineSimilarity(lspan, rspan); - rightIndexes[0]++; - } - rightIndexes[0] = 0; - leftIndexes[0]++; - } - - return new TensorSpan(values, 0, [dim1, dim2], []); - - } - #endregion - - #region CosPi - /// Computes the element-wise cosine of the value in the specified tensor that has been multiplied by Pi and returns a new with the results. - /// The input - /// - /// - /// This method effectively computes .CosPi([i]). - /// - /// - /// The angles in x must be in radians. Use or multiply by .Pi/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 TensorSpan CosPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.CosPi); - } - - /// Computes the element-wise cosine of the value in the specified tensor that has been multiplied by Pi in place. - /// The input - /// - /// - /// This method effectively computes .CosPi([i]). - /// - /// - /// The angles in x must be in radians. Use or multiply by .Pi/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 TensorSpan CosPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.CosPi, true); - } - #endregion - - #region DegreesToRadians - /// - /// Computes the element-wise conversion of each number of degrees in the specified tensor to radians and returns a new tensor with the results. - /// - /// The input . - public static TensorSpan DegreesToRadians(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.DegreesToRadians); - } - - /// - /// Computes the element-wise conversion of each number of degrees in the specified tensor to radians in place. - /// - /// The input . - public static TensorSpan DegreesToRadiansInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.DegreesToRadians, true); - } - #endregion - - #region Distance - /// - /// Computes the distance between two points, specified as non-empty, equal-length tensors of numbers, in Euclidean space. - /// - /// The input . - /// The input . - public static T Distance(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperTwoSpanInTOut(left, right, TensorPrimitives.Distance); - } - - #endregion - - #region Divide - /// - /// Divides each element of by and returns a new with the result. - /// - /// Input . - /// The divisor - public static TensorSpan Divide(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T[] values = new T[input.FlattenedLength]; - TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Divide(span, val, ospan); - return output; - } - - /// - /// Divides each element of by in place. - /// - /// Input . - /// The divisor - public static TensorSpan DivideInPlace(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Divide(span, val, ospan); - return output; - } - - /// - /// Divides by each element of and returns a new with the result."/> - /// - /// The value to be divided. - /// The divisor. - public static TensorSpan Divide(T val, TensorSpan input) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T[] values = new T[input.FlattenedLength]; - TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Divide(val, span, ospan); - return output; - } - - /// - /// Divides by each element of in place. - /// - /// The value to be divided. - /// The divisor. - public static TensorSpan DivideInPlace(T val, TensorSpan input) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Divide(val, span, ospan); - return output; - } - - /// - /// Divides each element of by its corresponding element in and returns - /// a new with the result. - /// - /// The to be divided. - /// The divisor. - public static TensorSpan Divide(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Divide); - } - - /// - /// Divides each element of by its corresponding element in in place. - /// - /// The to be divided. - /// The divisor. - public static TensorSpan DivideInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IDivisionOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Divide, true); - } - #endregion - - #region Dot - /// - /// Computes the dot product of two tensors containing numbers. - /// - /// The input . - /// The input . - public static T Dot(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity, IMultiplicativeIdentity, IMultiplyOperators - { - return TensorPrimitivesHelperTwoSpanInTOut(left, right, TensorPrimitives.Dot); - } - - #endregion - - #region Exp - /// - /// Computes the element-wise result of raising e to the single-precision floating-point number powers in the specified tensor. - /// - /// The input . - public static TensorSpan Exp(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp); - } - - /// - /// Computes the element-wise result of raising e to the single-precision floating-point number powers in the specified tensor. - /// - /// The input . - public static TensorSpan ExpInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp, true); - } - #endregion - - #region Exp10 - /// - /// Computes the element-wise result of raising 10 to the number powers in the specified tensor. - /// - /// The input . - public static TensorSpan Exp10(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10); - } - - /// - /// Computes the element-wise result of raising 10 to the number powers in the specified tensor. - /// - /// The input . - public static TensorSpan Exp10InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10, true); - } - #endregion - - #region Exp10M1 - /// Computes the element-wise result of raising 10 to the number powers in the specified tensor, minus one. - /// The input . - public static TensorSpan Exp10M1(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10M1); - } - - /// Computes the element-wise result of raising 10 to the number powers in the specified tensor, minus one. - /// The input . - public static TensorSpan Exp10M1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp10M1, true); - } - #endregion - - #region Exp2 - /// Computes the element-wise result of raising 2 to the number powers in the specified tensor. - /// The input . - public static TensorSpan Exp2(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2); - } - - /// Computes the element-wise result of raising 2 to the number powers in the specified tensor. - /// The input . - public static TensorSpan Exp2InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2, true); - } - #endregion - - #region Exp2M1 - /// Computes the element-wise result of raising 2 to the number powers in the specified tensor, minus one. - /// The input . - public static TensorSpan Exp2M1(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2M1); - } - - /// Computes the element-wise result of raising 2 to the number powers in the specified tensor, minus one. - /// The input . - public static TensorSpan Exp2M1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Exp2M1, true); - } - #endregion - - #region ExpM1 - /// Computes the element-wise result of raising e to the number powers in the specified tensor, minus 1. - /// The input . - public static TensorSpan ExpM1(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.ExpM1); - } - - /// Computes the element-wise result of raising e to the number powers in the specified tensor, minus 1. - /// The input . - public static TensorSpan ExpM1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.ExpM1, true); - } - #endregion - - #region Floor - /// Computes the element-wise floor of numbers in the specified tensor. - /// The input . - public static TensorSpan Floor(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Floor); - } - - /// Computes the element-wise floor of numbers in the specified tensor. - /// The input . - public static TensorSpan FloorInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Floor, true); - } - #endregion - - #region Hypotenuse - /// - /// Computes the element-wise hypotenuse given values from two tensors representing the lengths of the shorter sides in a right-angled triangle. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left . - /// Right . - public static TensorSpan Hypotenuse(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Hypot); - } - - /// - /// Computes the element-wise hypotenuse given values from two tensors representing the lengths of the shorter sides in a right-angled triangle. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left . - /// Right . - public static TensorSpan HypotenuseInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Hypot, true); - } - #endregion - - #region Ieee754Remainder - /// Computes the element-wise remainder of the numbers in the specified tensors. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// Left . - /// Right . - public static TensorSpan Ieee754Remainder(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Ieee754Remainder); - } - - /// - /// Computes the element-wise remainder of the numbers in the specified tensors. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left . - /// Right . - public static TensorSpan Ieee754RemainderInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Ieee754Remainder, true); - } - #endregion - - #region ILogB - /// Computes the element-wise floor of numbers in the specified tensor. - /// The input . - public static TensorSpan ILogB(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPointIeee754 - { - return TensorPrimitivesHelperSpanInIntSpanOut(input, TensorPrimitives.ILogB); - } - #endregion - - #region IndexOfMax - /// Searches for the index of the largest number in the specified tensor. - /// The input . - public static int IndexOfMax(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - return TensorPrimitives.IndexOfMax(span); - } - #endregion - - #region IndexOfMaxMagnitude - /// Searches for the index of the number with the largest magnitude in the specified tensor. - /// The input . - public static int IndexOfMaxMagnitude(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - return TensorPrimitives.IndexOfMaxMagnitude(span); - } - #endregion - - #region IndexOfMin - /// Searches for the index of the smallest number in the specified tensor. - /// The input . - public static int IndexOfMin(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - return TensorPrimitives.IndexOfMin(span); - } - #endregion - - #region IndexOfMinMagnitude - /// - /// Searches for the index of the number with the smallest magnitude in the specified tensor. - /// - /// The input . - public static int IndexOfMinMagnitude(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - return TensorPrimitives.IndexOfMinMagnitude(span); - } - #endregion - - #region LeadingZeroCount - /// - /// Computes the element-wise leading zero count of numbers in the specified tensor. - /// - /// The input . - public static TensorSpan LeadingZeroCount(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LeadingZeroCount); - } - - /// - /// Computes the element-wise leading zero count of numbers in the specified tensor. - /// - /// The input . - public static TensorSpan LeadingZeroCountInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LeadingZeroCount, true); - } - #endregion - - #region Log - - /// - /// Takes the natural logarithm of each element of the and returns a new with the result. - /// - /// The to take the natural logarithm of. - public static TensorSpan Log(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log); - } - - /// - /// Takes the natural logarithm of each element of the in place. - /// - /// The to take the natural logarithm of. - public static TensorSpan LogInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log, true); - } - #endregion - - #region Log10 - - /// - /// Takes the base 10 logarithm of each element of the and returns a new with the result. - /// - /// The to take the base 10 logarithm of. - public static TensorSpan Log10(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10); - } - - /// - /// Takes the base 10 logarithm of each element of the in place. - /// - /// The to take the base 10 logarithm of. - public static TensorSpan Log10InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10, true); - } - #endregion - - #region Log10P1 - /// - /// Takes the base 10 logarithm plus 1 of each element of the and returns a new with the result. - /// - /// The to take the base 10 logarithm of. - public static TensorSpan Log10P1(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10P1); - } - - /// - /// Takes the base 10 logarithm plus 1 of each element of the in place. - /// - /// The to take the base 10 logarithm of. - public static TensorSpan Log10P1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log10P1, true); - } - #endregion - - #region Log2 - /// - /// Takes the base 2 logarithm of each element of the and returns a new with the result. - /// - /// The to take the base 2 logarithm of. - public static TensorSpan Log2(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2); - } - - /// - /// Takes the base 2 logarithm of each element of the in place. - /// - /// The to take the base 2 logarithm of. - public static TensorSpan Log2InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2, true); - } - #endregion - - #region Log2P1 - /// - /// Takes the base 2 logarithm plus 1 of each element of the and returns a new with the result. - /// - /// The to take the base 2 logarithm of. - public static TensorSpan Log2P1(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2P1); - } - - /// - /// Takes the base 2 logarithm plus 1 of each element of the in place. - /// - /// The to take the base 2 logarithm of. - public static TensorSpan Log2P1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Log2P1, true); - } - #endregion - - #region LogP1 - /// - /// Takes the natural logarithm plus 1 of each element of the and returns a new with the result. - /// - /// The to take the natural logarithm of. - public static TensorSpan LogP1(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LogP1); - } - - /// - /// Takes the natural logarithm plus 1 of each element of the in place. - /// - /// The to take the natural logarithm of. - public static TensorSpan LogP1InPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ILogarithmicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.LogP1, true); - } - #endregion - - #region Max - /// Searches for the largest number in the specified tensor. - /// The input .. - public static T Max(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Max); - } - #endregion - - #region MaxMagnitude - /// Searches for the number with the largest magnitude in the specified tensor. - /// The input .. - public static T MaxMagnitude(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MaxMagnitude); - } - #endregion - - #region MaxNumber - /// Searches for the largest number in the specified tensor. - /// The input .. - public static T MaxNumber(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MaxNumber); - } - #endregion - - #region Min - /// Searches for the smallest number in the specified tensor. - /// The input . - public static T Min(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Min); - } - #endregion - - #region MinMagnitude - /// Searches for the number with the smallest magnitude in the specified tensor. - /// The input . - public static T MinMagnitude(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MinMagnitude); - } - #endregion - - #region MinNumber - /// Searches for the smallest number in the specified tensor. - /// The input .. - public static T MinNumber(TensorSpan input) - where T : IEquatable, IEqualityOperators, INumber - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.MinNumber); - } - #endregion - - #region Multiply - /// - /// Multiplies each element of with and returns a new with the result. - /// - /// Input - /// value to multiply by. - public static TensorSpan Multiply(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T[] values = new T[input.FlattenedLength]; - TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Multiply(span, val, ospan); - return output; - } - - /// - /// Multiplies each element of with in place. - /// - /// Input - /// value to multiply by. - public static TensorSpan MultiplyInPlace(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Multiply(span, val, ospan); - return output; - } - - /// - /// Multiplies each element of with and returns a new with the result. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left for multiplication. - /// Right for multiplication. - public static TensorSpan Multiply(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Multiply); - } - - /// - /// Multiplies each element of with in place. - /// If the shapes are not the same they are broadcast to the smallest compatible shape. - /// - /// Left for multiplication. - /// Right for multiplication. - public static TensorSpan MultiplyInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IMultiplyOperators, IMultiplicativeIdentity - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Multiply, true); - } - #endregion - - #region Negate - /// Computes the element-wise negation of each number in the specified tensor. - /// The - public static TensorSpan Negate(TensorSpan input) - where T : IEquatable, IEqualityOperators, IUnaryNegationOperators - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Negate); - } - - /// Computes the element-wise negation of each number in the specified tensor. - /// The - public static TensorSpan NegateInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IUnaryNegationOperators - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Negate, true); - } - #endregion - - #region Norm - - /// - /// Takes the norm of the and returns the result. - /// - /// The to take the norm of. - public static T Norm(TensorSpan input) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - return TensorPrimitives.Norm(span); - } - #endregion - - #region OnesComplement - /// Computes the element-wise one's complement of numbers in the specified tensor. - /// The - public static TensorSpan OnesComplement(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.OnesComplement); - } - - /// Computes the element-wise one's complement of numbers in the specified tensor. - /// The - public static TensorSpan OnesComplementInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.OnesComplement, true); - } - #endregion - - #region PopCount - /// Computes the element-wise population count of numbers in the specified tensor. - /// The - public static TensorSpan PopCount(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.PopCount); - } - - /// Computes the element-wise population count of numbers in the specified tensor. - /// The - public static TensorSpan PopCountInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.PopCount, true); - } - #endregion - - #region Pow - /// Computes the element-wise power of a number in a specified tensor raised to a number in another specified tensors. - /// The input . - /// The second input - public static TensorSpan Pow(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IPowerFunctions - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Pow); - } - - /// Computes the element-wise power of a number in a specified tensor raised to a number in another specified tensors. - /// The input . - /// The second input - public static TensorSpan PowInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IPowerFunctions - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Pow, true); - } - #endregion - - #region Product - /// Computes the product of all elements in the specified non-empty tensor of numbers. - /// The input . - public static T Product(TensorSpan input) - where T : IEquatable, IEqualityOperators, IMultiplicativeIdentity, IMultiplyOperators - { - return TensorPrimitivesHelperSpanInTOut(input, TensorPrimitives.Product); - } - #endregion - - #region RadiansToDegrees - /// Computes the element-wise conversion of each number of radians in the specified tensor to degrees. - /// The input . - public static TensorSpan RadiansToDegrees(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.RadiansToDegrees); - } - - /// Computes the element-wise conversion of each number of radians in the specified tensor to degrees. - /// The input . - public static TensorSpan RadiansToDegreesInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.RadiansToDegrees, true); - } - #endregion - - #region Reciprocal - /// Computes the element-wise reciprocal of numbers in the specified tensor. - /// The input . - public static TensorSpan Reciprocal(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Reciprocal); - } - - /// Computes the element-wise reciprocal of numbers in the specified tensor. - /// The input . - public static TensorSpan ReciprocalInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Reciprocal, true); - } - #endregion - - #region Round - /// Computes the element-wise rounding of the numbers in the specified tensor - /// The input . - public static TensorSpan Round(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Round); - } - - /// Computes the element-wise rounding of the numbers in the specified tensor - /// The input . - public static TensorSpan RoundInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Round, true); - } - #endregion - - #region Sigmoid - /// Computes the element-wise sigmoid function on the specified non-empty tensor of numbers. - /// The input . - public static TensorSpan Sigmoid(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sigmoid); - } - - /// Computes the element-wise sigmoid function on the specified non-empty tensor of numbers. - /// The input . - public static TensorSpan SigmoidInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sigmoid, true); - } - #endregion - - #region Sin - - /// - /// Takes the sin of each element of the and returns a new with the result. - /// - /// The to take the sin of. - public static TensorSpan Sin(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sin); - } - - /// - /// Takes the sin of each element of the in place. - /// - /// The to take the sin of. - public static TensorSpan SinInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sin, true); - } - #endregion - - #region Sinh - /// Computes the element-wise hyperbolic sine of each radian angle in the specified tensor. - /// The to take the sin of. - public static TensorSpan Sinh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sinh); - } - - /// Computes the element-wise hyperbolic sine of each radian angle in the specified tensor. - /// The to take the sin of. - public static TensorSpan SinhInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sinh, true); - } - #endregion - - #region SinPi - /// Computes the element-wise sine of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static TensorSpan SinPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SinPi); - } - - /// Computes the element-wise sine of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static TensorSpan SinPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SinPi, true); - } - #endregion - - #region SoftMax - /// Computes the softmax function over the specified non-empty tensor of numbers. - /// The to take the sin of. - public static TensorSpan SoftMax(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SoftMax); - } - - /// Computes the softmax function over the specified non-empty tensor of numbers. - /// The to take the sin of. - public static TensorSpan SoftMaxInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IExponentialFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.SoftMax, true); - } - #endregion - - #region Sqrt - /// - /// Takes the square root of each element of the and returns a new with the result. - /// - /// The to take the square root of. - public static TensorSpan Sqrt(TensorSpan input) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sqrt); - } - - /// - /// Takes the square root of each element of the in place. - /// - /// The to take the square root of. - public static TensorSpan SqrtInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IRootFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Sqrt, true); - } - #endregion - - #region Subtract - /// - /// Subtracts from each element of and returns a new with the result. - /// - /// The with values to be subtracted from. - /// The value to subtract. - public static TensorSpan Subtract(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T[] values = new T[input.FlattenedLength]; - TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Subtract(span, val, ospan); - return output; - } - - /// - /// Subtracts from each element of in place. - /// - /// The with values to be subtracted from. - /// The value to subtract. - public static TensorSpan SubtractInPlace(TensorSpan input, T val) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Subtract(span, val, ospan); - return output; - } - - /// - /// Subtracts each element of from and returns a new with the result. - /// - /// The value to be subtracted from. - /// The values to subtract. - public static TensorSpan Subtract(T val, TensorSpan input) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - T[] values = new T[input.FlattenedLength]; - TensorSpan output = new TensorSpan(values, 0, input.Lengths, default); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Subtract(val, span, ospan); - return output; - } - - /// - /// Subtracts each element of from in place. - /// - /// The value to be subtracted from. - /// The values to subtract. - public static TensorSpan SubtractInPlace(T val, TensorSpan input) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = input; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - TensorPrimitives.Subtract(val, span, ospan); - return output; - } - - /// - /// Subtracts each element of from and returns a new with the result. - /// - /// The of values to be subtracted from. - /// The of values to subtract. - public static TensorSpan Subtract(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Subtract); - } - - /// - /// Subtracts each element of from in place. - /// - /// The of values to be subtracted from. - /// The of values to subtract. - public static TensorSpan SubtractInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, ISubtractionOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Subtract, true); - } - #endregion - - #region Sum - /// - /// Sums all the elements of the and returns the result. - /// - /// The to sum. - public static T Sum(TensorSpan input) - where T : IEquatable, IEqualityOperators, IAdditionOperators, IAdditiveIdentity - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - return TensorPrimitives.Sum(span); - } - #endregion - - #region Tan - /// Computes the element-wise tangent of the value in the specified tensor. - /// The to take the sin of. - public static TensorSpan Tan(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tan); - } - - /// Computes the element-wise tangent of the value in the specified tensor. - /// The to take the sin of. - public static TensorSpan TanInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tan, true); - } - #endregion - - #region Tanh - /// Computes the element-wise hyperbolic tangent of each radian angle in the specified tensor. - /// The to take the sin of. - public static TensorSpan Tanh(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tanh); - } - - /// Computes the element-wise hyperbolic tangent of each radian angle in the specified tensor. - /// The to take the sin of. - public static TensorSpan TanhInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IHyperbolicFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Tanh, true); - } - #endregion - - #region TanPi - /// Computes the element-wise tangent of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static TensorSpan TanPi(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TanPi); - } - - /// Computes the element-wise tangent of the value in the specified tensor that has been multiplied by Pi. - /// The to take the sin of. - public static TensorSpan TanPiInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, ITrigonometricFunctions - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TanPi, true); - } - #endregion - - #region TrailingZeroCount - /// Computes the element-wise trailing zero count of numbers in the specified tensor. - /// The input . - public static TensorSpan TrailingZeroCount(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TrailingZeroCount); - } - - /// Computes the element-wise trailing zero count of numbers in the specified tensor. - /// The input . - public static TensorSpan TrailingZeroCountInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IBinaryInteger - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.TrailingZeroCount, true); - } - #endregion - - #region Truncate - /// Computes the element-wise truncation of numbers in the specified tensor. - /// The input . - public static TensorSpan Truncate(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Truncate); - } - - /// Computes the element-wise truncation of numbers in the specified tensor. - /// The input . - public static TensorSpan TruncateInPlace(TensorSpan input) - where T : IEquatable, IEqualityOperators, IFloatingPoint - { - return TensorPrimitivesHelperSpanInSpanOut(input, TensorPrimitives.Truncate, true); - } - #endregion - - #region Xor - /// Computes the element-wise XOR of numbers in the specified tensors. - /// The left . - /// The right . - public static TensorSpan Xor(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Xor); - } - - /// Computes the element-wise XOR of numbers in the specified tensors. - /// The left . - /// The right . - public static TensorSpan XorInPlace(TensorSpan left, TensorSpan right) - where T : IEquatable, IEqualityOperators, IBitwiseOperators - { - return TensorPrimitivesHelperTwoSpanInSpanOut(left, right, TensorPrimitives.Xor, true); - } - #endregion - - #region TensorPrimitivesHelpers - private delegate void PerformCalculationSpanInSpanOut(ReadOnlySpan input, Span output) - where T : IEquatable, IEqualityOperators; - - private delegate void PerformCalculationSpanInTInSpanOut(ReadOnlySpan input, T value, Span output) - where T : IEquatable, IEqualityOperators; - - private delegate void PerformCalculationTwoSpanInSpanOut(ReadOnlySpan input, ReadOnlySpan inputTwo, Span output) - where T : IEquatable, IEqualityOperators; - - private delegate void PerformCalculationTFromSpanInTToSpanOut(ReadOnlySpan input, Span output) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase; - - private delegate T PerformCalculationTwoSpanInTOut(ReadOnlySpan input, ReadOnlySpan inputTwo) - where T : IEquatable, IEqualityOperators; - - private delegate void PerformCalculationSpanInIntSpanOut(ReadOnlySpan input, Span output) - where T : IEquatable, IEqualityOperators; - - private delegate T PerformCalculationSpanInTOut(ReadOnlySpan input) - where T : IEquatable, IEqualityOperators; - - private static T TensorPrimitivesHelperSpanInTOut(TensorSpan input, PerformCalculationSpanInTOut performCalculation) - where T : IEquatable, IEqualityOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - return performCalculation(span); - } - - private static TensorSpan TensorPrimitivesHelperSpanInIntSpanOut(TensorSpan input, PerformCalculationSpanInIntSpanOut performCalculation) - where T : IEquatable, IEqualityOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - int[] data = new int[input.FlattenedLength]; - performCalculation(span, data); - return new TensorSpan(data, 0, input.Lengths, input.Strides); - } - - private static T TensorPrimitivesHelperTwoSpanInTOut(TensorSpan left, TensorSpan right, PerformCalculationTwoSpanInTOut performCalculation) - where T : IEquatable, IEqualityOperators - { - // If not in place but sizes are the same. - if (left.Lengths.SequenceEqual(right.Lengths)) - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); - return performCalculation(span, rspan); - } - // Not in place and broadcasting needs to happen. - else - { - // Have a couple different possible cases here. - // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) - // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) - // Because we are returning a single T though we need to actual realize the broadcasts at this point to perform the calculations. - - var broadcastedLeft = Broadcast(left, right); - var broadcastedRight = Broadcast(right, left); - - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref broadcastedLeft._reference, (int)broadcastedLeft.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref broadcastedRight._reference, (int)broadcastedRight.FlattenedLength); - return performCalculation(span, rspan); - } - } - - private static TensorSpan TensorPrimitivesHelperSpanInSpanOut(TensorSpan input, PerformCalculationSpanInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = inPlace ? input : new TensorSpan(new T[input.FlattenedLength], 0, input.Lengths, input.Strides); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - performCalculation(span, ospan); - return output; - } - - private static TensorSpan TensorPrimitivesHelperSpanInTInSpanOut(TensorSpan input, T value, PerformCalculationSpanInTInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input.FlattenedLength); - TensorSpan output = inPlace ? input : new TensorSpan(new T[input.FlattenedLength], 0, input.Lengths, input.Strides); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - performCalculation(span, value, ospan); - return output; - } - - private static TensorSpan TensorPrimitivesHelperTFromSpanInTToSpanOut(TensorSpan input, PerformCalculationTFromSpanInTToSpanOut performCalculation) - where TFrom : IEquatable, IEqualityOperators, INumberBase - where TTo : INumberBase - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref input._reference, (int)input._flattenedLength); - TTo[] data = new TTo[(int)input.FlattenedLength]; - TensorSpan output = new TensorSpan(data, 0, input.Lengths, input.Strides); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output._flattenedLength); - performCalculation(span, ospan); - return output; - } - - private static TensorSpan TensorPrimitivesHelperTwoSpanInSpanOut(TensorSpan left, TensorSpan right, PerformCalculationTwoSpanInSpanOut performCalculation, bool inPlace = false) - where T : IEquatable, IEqualityOperators - { - if (inPlace && !left.Lengths.SequenceEqual(right.Lengths)) - ThrowHelper.ThrowArgument_InPlaceInvalidShape(); - - TensorSpan output; - if (inPlace) - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); - output = left; - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - performCalculation(span, rspan, ospan); - } - // If not in place but sizes are the same. - else if (left.Lengths.SequenceEqual(right.Lengths)) - { - ReadOnlySpan span = MemoryMarshal.CreateSpan(ref left._reference, (int)left.FlattenedLength); - ReadOnlySpan rspan = MemoryMarshal.CreateSpan(ref right._reference, (int)right.FlattenedLength); - output = new TensorSpan(new T[left.FlattenedLength], 0, left.Lengths, left.Strides); - Span ospan = MemoryMarshal.CreateSpan(ref output._reference, (int)output.FlattenedLength); - performCalculation(span, rspan, ospan); - return output; - } - // Not in place and broadcasting needs to happen. - else - { - // Have a couple different possible cases here. - // 1 - Both tensors have row contiguous memory (i.e. a 1x5 being broadcast to a 5x5) - // 2 - One tensor has row contiguous memory and the right has column contiguous memory (i.e. a 1x5 and a 5x1) - - nint[] newSize = TensorHelpers.GetSmallestBroadcastableSize(left.Lengths, right.Lengths); - - TensorSpan broadcastedLeft = TensorSpan.BroadcastTo(left, newSize); - TensorSpan broadcastedRight = TensorSpan.BroadcastTo(right, newSize); - - output = new TensorSpan(new T[TensorSpanHelpers.CalculateTotalLength(newSize)], newSize, default); - nint rowLength = newSize[^1]; - Span ospan; - Span ispan; - Span buffer = new T[rowLength]; - - scoped Span curIndex; - nint[]? curIndexArray; - if (newSize.Length > 6) - { - curIndexArray = ArrayPool.Shared.Rent(newSize.Length); - curIndex = curIndexArray; - } - else - { - curIndexArray = null; - curIndex = stackalloc nint[newSize.Length]; - } - - int outputOffset = 0; - // ADD IN CASE WHERE NEITHER ARE ROW CONTIGUOUS - // tensor not row contiguous - if (broadcastedLeft.Strides[^1] == 0) - { - while (outputOffset < output.FlattenedLength) - { - ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); - buffer.Fill(broadcastedLeft[curIndex]); - ispan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndex], (int)rowLength); - performCalculation(buffer, ispan, ospan); - outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); - } - } - // right not row contiguous - else if (broadcastedRight.Strides[^1] == 0) - { - while (outputOffset < output.FlattenedLength) - { - ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); - buffer.Fill(broadcastedRight[curIndex]); - ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndex], (int)rowLength); - performCalculation(ispan, buffer, ospan); - outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); - } - } - // both row contiguous - else - { - Span rspan; - while (outputOffset < output.FlattenedLength) - { - ospan = MemoryMarshal.CreateSpan(ref Unsafe.Add(ref output._reference, outputOffset), (int)rowLength); - ispan = MemoryMarshal.CreateSpan(ref broadcastedLeft[curIndex], (int)rowLength); - rspan = MemoryMarshal.CreateSpan(ref broadcastedRight[curIndex], (int)rowLength); - performCalculation(ispan, rspan, ospan); - outputOffset += (int)rowLength; - TensorSpanHelpers.AdjustIndexes(broadcastedLeft.Rank - 2, 1, curIndex, broadcastedLeft.Lengths); - } - } - - if (curIndexArray != null) - ArrayPool.Shared.Return(curIndexArray); - } - return output; - } - #endregion - #endregion - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs index 8cb4d7ab957dd2..4ccdb305b596c0 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs @@ -216,5 +216,11 @@ internal static void ThrowArgument_IncompatibleDimensions(nint leftDim, nint rig { throw new ArgumentException(SR.Format(SR.Argument_IncompatibleDimensions, leftDim, rightDim)); } + + [DoesNotReturn] + internal static void ThrowArgument_StackShapesNotSame() + { + throw new ArgumentException(SR.ThrowArgument_StackShapesNotSame); + } } } diff --git a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs index d2e213e9372640..d55745614646fe 100644 --- a/src/libraries/System.Numerics.Tensors/tests/Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/tests/Helpers.cs @@ -14,7 +14,7 @@ public static class Helpers public static IEnumerable TensorLengthsIncluding0 => Enumerable.Range(0, 257); public static IEnumerable TensorLengths => Enumerable.Range(1, 256); - public static IEnumerable TensorShapes => [[1], [2], [10], [1,1], [1,2], [2,2], [5, 5], [2, 2, 2], [5, 5, 5], [3, 3, 3, 3], [4, 4, 4, 4, 4]]; + public static IEnumerable TensorShapes => [[1], [2], [10], [1,1], [1,2], [2,2], [5, 5], [2, 2, 2], [5, 5, 5], [3, 3, 3, 3], [4, 4, 4, 4, 4], [1, 2, 3, 4, 5, 6, 7]]; // Tolerances taken from testing in the scalar math routines: // cf. https://github.com/dotnet/runtime/blob/89f7ad3b276fb0b48f20cb4e8408bdce85c2b415/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs index 3937cd4a940089..fa79cae4883f87 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs @@ -35,102 +35,57 @@ private static nint CalculateTotalLength(ReadOnlySpan lengths) } public delegate void TensorPrimitivesSpanInSpanOut(ReadOnlySpan input, Span output); - public delegate TensorSpan TensorSpanInSpanOut(TensorSpan input); + public delegate ref readonly TensorSpan TensorSpanInSpanOut(scoped in ReadOnlyTensorSpan input, in TensorSpan destination); + public delegate ref readonly TensorSpan TensorSpanInSpanOutInPlace(in TensorSpan input); public static IEnumerable SpanInSpanOutData() { - yield return Create(TensorPrimitives.Abs, TensorSpan.Abs); - yield return Create(TensorPrimitives.Abs, TensorSpan.AbsInPlace); - yield return Create(TensorPrimitives.Acos, TensorSpan.Acos); - yield return Create(TensorPrimitives.Acos, TensorSpan.AcosInPlace); - yield return Create(TensorPrimitives.Acosh, TensorSpan.Acosh); - yield return Create(TensorPrimitives.Acosh, TensorSpan.AcoshInPlace); - yield return Create(TensorPrimitives.AcosPi, TensorSpan.AcosPi); - yield return Create(TensorPrimitives.AcosPi, TensorSpan.AcosPiInPlace); - yield return Create(TensorPrimitives.Asin, TensorSpan.Asin); - yield return Create(TensorPrimitives.Asin, TensorSpan.AsinInPlace); - yield return Create(TensorPrimitives.Asinh, TensorSpan.Asinh); - yield return Create(TensorPrimitives.Asinh, TensorSpan.AsinhInPlace); - yield return Create(TensorPrimitives.AsinPi, TensorSpan.AsinPi); - yield return Create(TensorPrimitives.AsinPi, TensorSpan.AsinPiInPlace); - yield return Create(TensorPrimitives.Atan, TensorSpan.Atan); - yield return Create(TensorPrimitives.Atan, TensorSpan.AtanInPlace); - yield return Create(TensorPrimitives.Atanh, TensorSpan.Atanh); - yield return Create(TensorPrimitives.Atanh, TensorSpan.AtanhInPlace); - yield return Create(TensorPrimitives.AtanPi, TensorSpan.AtanPi); - yield return Create(TensorPrimitives.AtanPi, TensorSpan.AtanPiInPlace); - yield return Create(TensorPrimitives.Cbrt, TensorSpan.CubeRoot); - yield return Create(TensorPrimitives.Cbrt, TensorSpan.CubeRootInPlace); - yield return Create(TensorPrimitives.Ceiling, TensorSpan.Ceiling); - yield return Create(TensorPrimitives.Ceiling, TensorSpan.CeilingInPlace); - yield return Create(TensorPrimitives.Cos, TensorSpan.Cos); - yield return Create(TensorPrimitives.Cos, TensorSpan.CosInPlace); - yield return Create(TensorPrimitives.Cosh, TensorSpan.Cosh); - yield return Create(TensorPrimitives.Cosh, TensorSpan.CoshInPlace); - yield return Create(TensorPrimitives.CosPi, TensorSpan.CosPi); - yield return Create(TensorPrimitives.CosPi, TensorSpan.CosPiInPlace); - yield return Create(TensorPrimitives.DegreesToRadians, TensorSpan.DegreesToRadians); - yield return Create(TensorPrimitives.DegreesToRadians, TensorSpan.DegreesToRadiansInPlace); - yield return Create(TensorPrimitives.Exp, TensorSpan.Exp); - yield return Create(TensorPrimitives.Exp, TensorSpan.ExpInPlace); - yield return Create(TensorPrimitives.Exp10, TensorSpan.Exp10); - yield return Create(TensorPrimitives.Exp10, TensorSpan.Exp10InPlace); - yield return Create(TensorPrimitives.Exp10M1, TensorSpan.Exp10M1); - yield return Create(TensorPrimitives.Exp10M1, TensorSpan.Exp10M1InPlace); - yield return Create(TensorPrimitives.Exp2, TensorSpan.Exp2); - yield return Create(TensorPrimitives.Exp2, TensorSpan.Exp2InPlace); - yield return Create(TensorPrimitives.Exp2M1, TensorSpan.Exp2M1); - yield return Create(TensorPrimitives.Exp2M1, TensorSpan.Exp2M1InPlace); - yield return Create(TensorPrimitives.ExpM1, TensorSpan.ExpM1); - yield return Create(TensorPrimitives.ExpM1, TensorSpan.ExpM1InPlace); - yield return Create(TensorPrimitives.Floor, TensorSpan.Floor); - yield return Create(TensorPrimitives.Floor, TensorSpan.FloorInPlace); - yield return Create(TensorPrimitives.LeadingZeroCount, TensorSpan.LeadingZeroCount); - yield return Create(TensorPrimitives.LeadingZeroCount, TensorSpan.LeadingZeroCount); - yield return Create(TensorPrimitives.Log, TensorSpan.Log); - yield return Create(TensorPrimitives.Log, TensorSpan.LogInPlace); - yield return Create(TensorPrimitives.Log10, TensorSpan.Log10); - yield return Create(TensorPrimitives.Log10, TensorSpan.Log10InPlace); - yield return Create(TensorPrimitives.Log10P1, TensorSpan.Log10P1); - yield return Create(TensorPrimitives.Log10P1, TensorSpan.Log10P1InPlace); - yield return Create(TensorPrimitives.Log2, TensorSpan.Log2); - yield return Create(TensorPrimitives.Log2, TensorSpan.Log2InPlace); - yield return Create(TensorPrimitives.Log2P1, TensorSpan.Log2P1); - yield return Create(TensorPrimitives.Log2P1, TensorSpan.Log2P1InPlace); - yield return Create(TensorPrimitives.LogP1, TensorSpan.LogP1); - yield return Create(TensorPrimitives.LogP1, TensorSpan.LogP1InPlace); - yield return Create(TensorPrimitives.Negate, TensorSpan.Negate); - yield return Create(TensorPrimitives.Negate, TensorSpan.NegateInPlace); - yield return Create(TensorPrimitives.OnesComplement, TensorSpan.OnesComplement); - yield return Create(TensorPrimitives.OnesComplement, TensorSpan.OnesComplementInPlace); - yield return Create(TensorPrimitives.PopCount, TensorSpan.PopCount); - yield return Create(TensorPrimitives.PopCount, TensorSpan.PopCountInPlace); - yield return Create(TensorPrimitives.RadiansToDegrees, TensorSpan.RadiansToDegrees); - yield return Create(TensorPrimitives.RadiansToDegrees, TensorSpan.RadiansToDegreesInPlace); - yield return Create(TensorPrimitives.Reciprocal, TensorSpan.Reciprocal); - yield return Create(TensorPrimitives.Reciprocal, TensorSpan.ReciprocalInPlace); - yield return Create(TensorPrimitives.Round, TensorSpan.Round); - yield return Create(TensorPrimitives.Round, TensorSpan.RoundInPlace); - yield return Create(TensorPrimitives.Sigmoid, TensorSpan.Sigmoid); - yield return Create(TensorPrimitives.Sigmoid, TensorSpan.SigmoidInPlace); - yield return Create(TensorPrimitives.Sin, TensorSpan.Sin); - yield return Create(TensorPrimitives.Sin, TensorSpan.SinInPlace); - yield return Create(TensorPrimitives.Sinh, TensorSpan.Sinh); - yield return Create(TensorPrimitives.Sinh, TensorSpan.SinhInPlace); - yield return Create(TensorPrimitives.SinPi, TensorSpan.SinPi); - yield return Create(TensorPrimitives.SinPi, TensorSpan.SinPiInPlace); - yield return Create(TensorPrimitives.SoftMax, TensorSpan.SoftMax); - yield return Create(TensorPrimitives.SoftMax, TensorSpan.SoftMaxInPlace); - yield return Create(TensorPrimitives.Sqrt, TensorSpan.Sqrt); - yield return Create(TensorPrimitives.Sqrt, TensorSpan.SqrtInPlace); - yield return Create(TensorPrimitives.Tan, TensorSpan.Tan); - yield return Create(TensorPrimitives.Tan, TensorSpan.TanInPlace); - yield return Create(TensorPrimitives.Tanh, TensorSpan.Tanh); - yield return Create(TensorPrimitives.Tanh, TensorSpan.TanhInPlace); - yield return Create(TensorPrimitives.TanPi, TensorSpan.TanPi); - yield return Create(TensorPrimitives.TanPi, TensorSpan.TanPiInPlace); - yield return Create(TensorPrimitives.Truncate, TensorSpan.Truncate); - yield return Create(TensorPrimitives.Truncate, TensorSpan.TruncateInPlace); + yield return Create(TensorPrimitives.Abs, Tensor.Abs); + yield return Create(TensorPrimitives.Acos, Tensor.Acos); + yield return Create(TensorPrimitives.Acosh, Tensor.Acosh); + yield return Create(TensorPrimitives.AcosPi, Tensor.AcosPi); + yield return Create(TensorPrimitives.Asin, Tensor.Asin); + yield return Create(TensorPrimitives.Asinh, Tensor.Asinh); + yield return Create(TensorPrimitives.AsinPi, Tensor.AsinPi); + yield return Create(TensorPrimitives.Atan, Tensor.Atan); + yield return Create(TensorPrimitives.Atanh, Tensor.Atanh); + yield return Create(TensorPrimitives.AtanPi, Tensor.AtanPi); + yield return Create(TensorPrimitives.Cbrt, Tensor.Cbrt); + yield return Create(TensorPrimitives.Ceiling, Tensor.Ceiling); + yield return Create(TensorPrimitives.Cos, Tensor.Cos); + yield return Create(TensorPrimitives.Cosh, Tensor.Cosh); + yield return Create(TensorPrimitives.CosPi, Tensor.CosPi); + yield return Create(TensorPrimitives.DegreesToRadians, Tensor.DegreesToRadians); + yield return Create(TensorPrimitives.Exp, Tensor.Exp); + yield return Create(TensorPrimitives.Exp10, Tensor.Exp10); + yield return Create(TensorPrimitives.Exp10M1, Tensor.Exp10M1); + yield return Create(TensorPrimitives.Exp2, Tensor.Exp2); + yield return Create(TensorPrimitives.Exp2M1, Tensor.Exp2M1); + yield return Create(TensorPrimitives.ExpM1, Tensor.ExpM1); + yield return Create(TensorPrimitives.Floor, Tensor.Floor); + yield return Create(TensorPrimitives.LeadingZeroCount, Tensor.LeadingZeroCount); + yield return Create(TensorPrimitives.Log, Tensor.Log); + yield return Create(TensorPrimitives.Log10, Tensor.Log10); + yield return Create(TensorPrimitives.Log10P1, Tensor.Log10P1); + yield return Create(TensorPrimitives.Log2, Tensor.Log2); + yield return Create(TensorPrimitives.Log2P1, Tensor.Log2P1); + yield return Create(TensorPrimitives.LogP1, Tensor.LogP1); + yield return Create(TensorPrimitives.Negate, Tensor.Negate); + yield return Create(TensorPrimitives.OnesComplement, Tensor.OnesComplement); + yield return Create(TensorPrimitives.PopCount, Tensor.PopCount); + yield return Create(TensorPrimitives.RadiansToDegrees, Tensor.RadiansToDegrees); + yield return Create(TensorPrimitives.Reciprocal, Tensor.Reciprocal); + yield return Create(TensorPrimitives.Round, Tensor.Round); + yield return Create(TensorPrimitives.Sigmoid, Tensor.Sigmoid); + yield return Create(TensorPrimitives.Sin, Tensor.Sin); + yield return Create(TensorPrimitives.Sinh, Tensor.Sinh); + yield return Create(TensorPrimitives.SinPi, Tensor.SinPi); + yield return Create(TensorPrimitives.SoftMax, Tensor.SoftMax); + yield return Create(TensorPrimitives.Sqrt, Tensor.Sqrt); + yield return Create(TensorPrimitives.Tan, Tensor.Tan); + yield return Create(TensorPrimitives.Tanh, Tensor.Tanh); + yield return Create(TensorPrimitives.TanPi, Tensor.TanPi); + yield return Create(TensorPrimitives.Truncate, Tensor.Truncate); static object[] Create(TensorPrimitivesSpanInSpanOut tensorPrimitivesMethod, TensorSpanInSpanOut tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; @@ -144,37 +99,44 @@ public void TensorExtensionsSpanInSpanOut(TensorPrimitivesSpanInSpanOut te { nint length = CalculateTotalLength(tensorLength); T[] data = new T[length]; + T[] data2 = new T[length]; T[] expectedOutput = new T[length]; FillTensor(data); TensorSpan x = Tensor.Create(data, tensorLength, []); + TensorSpan destination = Tensor.Create(data2, tensorLength, []); tensorPrimitivesOperation((ReadOnlySpan)data, expectedOutput); - TensorSpan results = tensorOperation(x); + TensorSpan results = tensorOperation(x, destination); Assert.Equal(tensorLength, results.Lengths); nint[] startingIndex = new nint[tensorLength.Length]; + + // the "Return" value ReadOnlySpan span = MemoryMarshal.CreateSpan(ref results[startingIndex], (int)length); + // the "destination" value + ReadOnlySpan destSpan = MemoryMarshal.CreateSpan(ref destination[startingIndex], (int)length); for (int i = 0; i < data.Length; i++) { Assert.Equal(expectedOutput[i], span[i]); + Assert.Equal(expectedOutput[i], destSpan[i]); } }); } public delegate T TensorPrimitivesSpanInTOut(ReadOnlySpan input); - public delegate T TensorSpanInTOut(TensorSpan input); + public delegate T TensorSpanInTOut(scoped in ReadOnlyTensorSpan input); public static IEnumerable SpanInFloatOutData() { - yield return Create(TensorPrimitives.Max, TensorSpan.Max); - yield return Create(TensorPrimitives.MaxMagnitude, TensorSpan.MaxMagnitude); - yield return Create(TensorPrimitives.MaxNumber, TensorSpan.MaxNumber); - yield return Create(TensorPrimitives.Min, TensorSpan.Min); - yield return Create(TensorPrimitives.MinMagnitude, TensorSpan.MinMagnitude); - yield return Create(TensorPrimitives.MinNumber, TensorSpan.MinNumber); - yield return Create(TensorPrimitives.Norm, TensorSpan.Norm); - yield return Create(TensorPrimitives.Product, TensorSpan.Product); - yield return Create(TensorPrimitives.Sum, TensorSpan.Sum); + yield return Create(TensorPrimitives.Max, Tensor.Max); + yield return Create(TensorPrimitives.MaxMagnitude, Tensor.MaxMagnitude); + yield return Create(TensorPrimitives.MaxNumber, Tensor.MaxNumber); + yield return Create(TensorPrimitives.Min, Tensor.Min); + yield return Create(TensorPrimitives.MinMagnitude, Tensor.MinMagnitude); + yield return Create(TensorPrimitives.MinNumber, Tensor.MinNumber); + yield return Create(TensorPrimitives.Norm, Tensor.Norm); + yield return Create(TensorPrimitives.Product, Tensor.Product); + yield return Create(TensorPrimitives.Sum, Tensor.Sum); static object[] Create(TensorPrimitivesSpanInTOut tensorPrimitivesMethod, TensorSpanInTOut tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; @@ -199,29 +161,20 @@ public void TensorExtensionsSpanInTOut(TensorPrimitivesSpanInTOut tensorPr } public delegate void TensorPrimitivesTwoSpanInSpanOut(ReadOnlySpan input, ReadOnlySpan inputTwo, Span output); - public delegate TensorSpan TensorTwoSpanInSpanOut(TensorSpan input, TensorSpan inputTwo); + public delegate ref readonly TensorSpan TensorTwoSpanInSpanOut(scoped in ReadOnlyTensorSpan input, scoped in ReadOnlyTensorSpan inputTwo, in TensorSpan destination); + public delegate ref readonly TensorSpan TensorTwoSpanInSpanOutInPlace(in TensorSpan input, scoped in ReadOnlyTensorSpan inputTwo); public static IEnumerable TwoSpanInSpanOutData() { - yield return Create(TensorPrimitives.Add, TensorSpan.Add); - yield return Create(TensorPrimitives.Add, TensorSpan.AddInPlace); - yield return Create(TensorPrimitives.Atan2, TensorSpan.Atan2); - yield return Create(TensorPrimitives.Atan2, TensorSpan.Atan2InPlace); - yield return Create(TensorPrimitives.Atan2Pi, TensorSpan.Atan2Pi); - yield return Create(TensorPrimitives.Atan2Pi, TensorSpan.Atan2PiInPlace); - yield return Create(TensorPrimitives.CopySign, TensorSpan.CopySign); - yield return Create(TensorPrimitives.CopySign, TensorSpan.CopySignInPlace); - yield return Create(TensorPrimitives.Divide, TensorSpan.Divide); - yield return Create(TensorPrimitives.Divide, TensorSpan.DivideInPlace); - yield return Create(TensorPrimitives.Hypot, TensorSpan.Hypotenuse); - yield return Create(TensorPrimitives.Hypot, TensorSpan.HypotenuseInPlace); - yield return Create(TensorPrimitives.Ieee754Remainder, TensorSpan.Ieee754Remainder); - yield return Create(TensorPrimitives.Ieee754Remainder, TensorSpan.Ieee754RemainderInPlace); - yield return Create(TensorPrimitives.Multiply, TensorSpan.Multiply); - yield return Create(TensorPrimitives.Multiply, TensorSpan.MultiplyInPlace); - yield return Create(TensorPrimitives.Pow, TensorSpan.Pow); - yield return Create(TensorPrimitives.Pow, TensorSpan.PowInPlace); - yield return Create(TensorPrimitives.Subtract, TensorSpan.Subtract); - yield return Create(TensorPrimitives.Subtract, TensorSpan.SubtractInPlace); + yield return Create(TensorPrimitives.Add, Tensor.Add); + yield return Create(TensorPrimitives.Atan2, Tensor.Atan2); + yield return Create(TensorPrimitives.Atan2Pi, Tensor.Atan2Pi); + yield return Create(TensorPrimitives.CopySign, Tensor.CopySign); + yield return Create(TensorPrimitives.Divide, Tensor.Divide); + yield return Create(TensorPrimitives.Hypot, Tensor.Hypot); + yield return Create(TensorPrimitives.Ieee754Remainder, Tensor.Ieee754Remainder); + yield return Create(TensorPrimitives.Multiply, Tensor.Multiply); + yield return Create(TensorPrimitives.Pow, Tensor.Pow); + yield return Create(TensorPrimitives.Subtract, Tensor.Subtract); static object[] Create(TensorPrimitivesTwoSpanInSpanOut tensorPrimitivesMethod, TensorTwoSpanInSpanOut tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; @@ -236,32 +189,38 @@ public void TensorExtensionsTwoSpanInSpanOut(TensorPrimitivesTwoSpanInSpanOut nint length = CalculateTotalLength(tensorLength); T[] data1 = new T[length]; T[] data2 = new T[length]; + T[] destData = new T[length]; T[] expectedOutput = new T[length]; FillTensor(data1); FillTensor(data2); TensorSpan x = Tensor.Create(data1, tensorLength, []); TensorSpan y = Tensor.Create(data2, tensorLength, []); + TensorSpan destination = Tensor.Create(destData, tensorLength, []); tensorPrimitivesOperation((ReadOnlySpan)data1, data2, expectedOutput); - TensorSpan results = tensorOperation(x, y); + TensorSpan results = tensorOperation(x, y, destination); Assert.Equal(tensorLength, results.Lengths); nint[] startingIndex = new nint[tensorLength.Length]; + // the "Return" value ReadOnlySpan span = MemoryMarshal.CreateSpan(ref results[startingIndex], (int)length); + // the "destination" value + ReadOnlySpan destSpan = MemoryMarshal.CreateSpan(ref destination[startingIndex], (int)length); for (int i = 0; i < data1.Length; i++) { Assert.Equal(expectedOutput[i], span[i]); + Assert.Equal(expectedOutput[i], destSpan[i]); } }); } public delegate T TensorPrimitivesTwoSpanInTOut(ReadOnlySpan input, ReadOnlySpan inputTwo); - public delegate T TensorTwoSpanInTOut(TensorSpan input, TensorSpan inputTwo); + public delegate T TensorTwoSpanInTOut(scoped in ReadOnlyTensorSpan input, scoped in ReadOnlyTensorSpan inputTwo); public static IEnumerable TwoSpanInFloatOutData() { - yield return Create(TensorPrimitives.Distance, TensorSpan.Distance); - yield return Create(TensorPrimitives.Dot, TensorSpan.Dot); + yield return Create(TensorPrimitives.Distance, Tensor.Distance); + yield return Create(TensorPrimitives.Dot, Tensor.Dot); static object[] Create(TensorPrimitivesTwoSpanInTOut tensorPrimitivesMethod, TensorTwoSpanInTOut tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs index d3a36377f32ca2..da33195220ca8a 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs @@ -38,97 +38,52 @@ private static nint CalculateTotalLength(ReadOnlySpan lengths) public static IEnumerable SpanInSpanOutData() { yield return Create(TensorPrimitives.Abs, Tensor.Abs); - yield return Create(TensorPrimitives.Abs, Tensor.AbsInPlace); yield return Create(TensorPrimitives.Acos, Tensor.Acos); - yield return Create(TensorPrimitives.Acos, Tensor.AcosInPlace); yield return Create(TensorPrimitives.Acosh, Tensor.Acosh); - yield return Create(TensorPrimitives.Acosh, Tensor.AcoshInPlace); yield return Create(TensorPrimitives.AcosPi, Tensor.AcosPi); - yield return Create(TensorPrimitives.AcosPi, Tensor.AcosPiInPlace); yield return Create(TensorPrimitives.Asin, Tensor.Asin); - yield return Create(TensorPrimitives.Asin, Tensor.AsinInPlace); yield return Create(TensorPrimitives.Asinh, Tensor.Asinh); - yield return Create(TensorPrimitives.Asinh, Tensor.AsinhInPlace); yield return Create(TensorPrimitives.AsinPi, Tensor.AsinPi); - yield return Create(TensorPrimitives.AsinPi, Tensor.AsinPiInPlace); yield return Create(TensorPrimitives.Atan, Tensor.Atan); - yield return Create(TensorPrimitives.Atan, Tensor.AtanInPlace); yield return Create(TensorPrimitives.Atanh, Tensor.Atanh); - yield return Create(TensorPrimitives.Atanh, Tensor.AtanhInPlace); yield return Create(TensorPrimitives.AtanPi, Tensor.AtanPi); - yield return Create(TensorPrimitives.AtanPi, Tensor.AtanPiInPlace); - yield return Create(TensorPrimitives.Cbrt, Tensor.CubeRoot); - yield return Create(TensorPrimitives.Cbrt, Tensor.CubeRootInPlace); + yield return Create(TensorPrimitives.Cbrt, Tensor.Cbrt); yield return Create(TensorPrimitives.Ceiling, Tensor.Ceiling); - yield return Create(TensorPrimitives.Ceiling, Tensor.CeilingInPlace); yield return Create(TensorPrimitives.Cos, Tensor.Cos); - yield return Create(TensorPrimitives.Cos, Tensor.CosInPlace); yield return Create(TensorPrimitives.Cosh, Tensor.Cosh); - yield return Create(TensorPrimitives.Cosh, Tensor.CoshInPlace); yield return Create(TensorPrimitives.CosPi, Tensor.CosPi); - yield return Create(TensorPrimitives.CosPi, Tensor.CosPiInPlace); yield return Create(TensorPrimitives.DegreesToRadians, Tensor.DegreesToRadians); - yield return Create(TensorPrimitives.DegreesToRadians, Tensor.DegreesToRadiansInPlace); yield return Create(TensorPrimitives.Exp, Tensor.Exp); - yield return Create(TensorPrimitives.Exp, Tensor.ExpInPlace); yield return Create(TensorPrimitives.Exp10, Tensor.Exp10); - yield return Create(TensorPrimitives.Exp10, Tensor.Exp10InPlace); yield return Create(TensorPrimitives.Exp10M1, Tensor.Exp10M1); - yield return Create(TensorPrimitives.Exp10M1, Tensor.Exp10M1InPlace); yield return Create(TensorPrimitives.Exp2, Tensor.Exp2); - yield return Create(TensorPrimitives.Exp2, Tensor.Exp2InPlace); yield return Create(TensorPrimitives.Exp2M1, Tensor.Exp2M1); - yield return Create(TensorPrimitives.Exp2M1, Tensor.Exp2M1InPlace); yield return Create(TensorPrimitives.ExpM1, Tensor.ExpM1); - yield return Create(TensorPrimitives.ExpM1, Tensor.ExpM1InPlace); yield return Create(TensorPrimitives.Floor, Tensor.Floor); - yield return Create(TensorPrimitives.Floor, Tensor.FloorInPlace); yield return Create(TensorPrimitives.LeadingZeroCount, Tensor.LeadingZeroCount); yield return Create(TensorPrimitives.LeadingZeroCount, Tensor.LeadingZeroCount); yield return Create(TensorPrimitives.Log, Tensor.Log); - yield return Create(TensorPrimitives.Log, Tensor.LogInPlace); yield return Create(TensorPrimitives.Log10, Tensor.Log10); - yield return Create(TensorPrimitives.Log10, Tensor.Log10InPlace); yield return Create(TensorPrimitives.Log10P1, Tensor.Log10P1); - yield return Create(TensorPrimitives.Log10P1, Tensor.Log10P1InPlace); yield return Create(TensorPrimitives.Log2, Tensor.Log2); - yield return Create(TensorPrimitives.Log2, Tensor.Log2InPlace); yield return Create(TensorPrimitives.Log2P1, Tensor.Log2P1); - yield return Create(TensorPrimitives.Log2P1, Tensor.Log2P1InPlace); yield return Create(TensorPrimitives.LogP1, Tensor.LogP1); - yield return Create(TensorPrimitives.LogP1, Tensor.LogP1InPlace); yield return Create(TensorPrimitives.Negate, Tensor.Negate); - yield return Create(TensorPrimitives.Negate, Tensor.NegateInPlace); yield return Create(TensorPrimitives.OnesComplement, Tensor.OnesComplement); - yield return Create(TensorPrimitives.OnesComplement, Tensor.OnesComplementInPlace); yield return Create(TensorPrimitives.PopCount, Tensor.PopCount); - yield return Create(TensorPrimitives.PopCount, Tensor.PopCountInPlace); yield return Create(TensorPrimitives.RadiansToDegrees, Tensor.RadiansToDegrees); - yield return Create(TensorPrimitives.RadiansToDegrees, Tensor.RadiansToDegreesInPlace); yield return Create(TensorPrimitives.Reciprocal, Tensor.Reciprocal); - yield return Create(TensorPrimitives.Reciprocal, Tensor.ReciprocalInPlace); yield return Create(TensorPrimitives.Round, Tensor.Round); - yield return Create(TensorPrimitives.Round, Tensor.RoundInPlace); yield return Create(TensorPrimitives.Sigmoid, Tensor.Sigmoid); - yield return Create(TensorPrimitives.Sigmoid, Tensor.SigmoidInPlace); yield return Create(TensorPrimitives.Sin, Tensor.Sin); - yield return Create(TensorPrimitives.Sin, Tensor.SinInPlace); yield return Create(TensorPrimitives.Sinh, Tensor.Sinh); - yield return Create(TensorPrimitives.Sinh, Tensor.SinhInPlace); yield return Create(TensorPrimitives.SinPi, Tensor.SinPi); - yield return Create(TensorPrimitives.SinPi, Tensor.SinPiInPlace); yield return Create(TensorPrimitives.SoftMax, Tensor.SoftMax); - yield return Create(TensorPrimitives.SoftMax, Tensor.SoftMaxInPlace); yield return Create(TensorPrimitives.Sqrt, Tensor.Sqrt); - yield return Create(TensorPrimitives.Sqrt, Tensor.SqrtInPlace); yield return Create(TensorPrimitives.Tan, Tensor.Tan); - yield return Create(TensorPrimitives.Tan, Tensor.TanInPlace); yield return Create(TensorPrimitives.Tanh, Tensor.Tanh); - yield return Create(TensorPrimitives.Tanh, Tensor.TanhInPlace); yield return Create(TensorPrimitives.TanPi, Tensor.TanPi); - yield return Create(TensorPrimitives.TanPi, Tensor.TanPiInPlace); yield return Create(TensorPrimitives.Truncate, Tensor.Truncate); - yield return Create(TensorPrimitives.Truncate, Tensor.TruncateInPlace); static object[] Create(PerformCalculationSpanInSpanOut tensorPrimitivesMethod, Func, Tensor> tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; @@ -199,25 +154,15 @@ public void TensorExtensionsSpanInTOut(PerformCalculationSpanInTOut tensor public static IEnumerable TwoSpanInSpanOutData() { yield return Create(TensorPrimitives.Add, Tensor.Add); - yield return Create(TensorPrimitives.Add, Tensor.AddInPlace); yield return Create(TensorPrimitives.Atan2, Tensor.Atan2); - yield return Create(TensorPrimitives.Atan2, Tensor.Atan2InPlace); yield return Create(TensorPrimitives.Atan2Pi, Tensor.Atan2Pi); - yield return Create(TensorPrimitives.Atan2Pi, Tensor.Atan2PiInPlace); yield return Create(TensorPrimitives.CopySign, Tensor.CopySign); - yield return Create(TensorPrimitives.CopySign, Tensor.CopySignInPlace); yield return Create(TensorPrimitives.Divide, Tensor.Divide); - yield return Create(TensorPrimitives.Divide, Tensor.DivideInPlace); - yield return Create(TensorPrimitives.Hypot, Tensor.Hypotenuse); - yield return Create(TensorPrimitives.Hypot, Tensor.HypotenuseInPlace); + yield return Create(TensorPrimitives.Hypot, Tensor.Hypot); yield return Create(TensorPrimitives.Ieee754Remainder, Tensor.Ieee754Remainder); - yield return Create(TensorPrimitives.Ieee754Remainder, Tensor.Ieee754RemainderInPlace); yield return Create(TensorPrimitives.Multiply, Tensor.Multiply); - yield return Create(TensorPrimitives.Multiply, Tensor.MultiplyInPlace); yield return Create(TensorPrimitives.Pow, Tensor.Pow); - yield return Create(TensorPrimitives.Pow, Tensor.PowInPlace); yield return Create(TensorPrimitives.Subtract, Tensor.Subtract); - yield return Create(TensorPrimitives.Subtract, Tensor.SubtractInPlace); static object[] Create(PerformCalculationTwoSpanInSpanOut tensorPrimitivesMethod, Func, Tensor, Tensor> tensorOperation) => new object[] { tensorPrimitivesMethod, tensorOperation }; @@ -422,7 +367,7 @@ public static void TensorFactoryCreateUninitializedTests() public static void TensorFactoryCreateTests() { // Basic tensor creation - Tensor t1 = Tensor.Create([1]); + Tensor t1 = Tensor.Create((ReadOnlySpan)([1])); Assert.Equal(1, t1.Rank); Assert.Equal(1, t1.Lengths.Length); Assert.Equal(1, t1.Lengths[0]); @@ -452,10 +397,10 @@ public static void TensorFactoryCreateTests() // Make sure lengths can't be negative Assert.Throws(() => { - Tensor t1 = Tensor.Create([-1]); + Tensor t1 = Tensor.Create((ReadOnlySpan)([-1])); }); - t1 = Tensor.Create([0]); + t1 = Tensor.Create((ReadOnlySpan)([0])); Assert.Equal(1, t1.Rank); Assert.Equal(1, t1.Lengths.Length); Assert.Equal(0, t1.Lengths[0]); @@ -463,7 +408,7 @@ public static void TensorFactoryCreateTests() Assert.Equal(0, t1.Strides[0]); Assert.False(t1.IsPinned); - t1 = Tensor.Create([]); + t1 = Tensor.Create((ReadOnlySpan)([])); Assert.Equal(1, t1.Rank); Assert.Equal(1, t1.Lengths.Length); Assert.Equal(0, t1.Lengths[0]); @@ -590,85 +535,85 @@ public static void TensorCosineSimilarityTests() Assert.Equal(0.81649, result[1, 1], .00001); } - [Fact] - public static void TensorSequenceEqualTests() - { - Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - Tensor equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([3], equal.Lengths.ToArray()); - Assert.True(equal[0]); - Assert.True(equal[1]); - Assert.True(equal[2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([1, 3], equal.Lengths.ToArray()); - Assert.True(equal[0, 0]); - Assert.True(equal[0, 1]); - Assert.True(equal[0, 2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 1, 3); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([1, 1, 3], equal.Lengths.ToArray()); - Assert.True(equal[0, 0, 0]); - Assert.True(equal[0, 0, 1]); - Assert.True(equal[0, 0, 2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); - equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([1, 3], equal.Lengths.ToArray()); - Assert.True(equal[0, 0]); - Assert.True(equal[0, 1]); - Assert.True(equal[0, 2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); - equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([3, 3], equal.Lengths.ToArray()); - Assert.True(equal[0, 0]); - Assert.False(equal[0, 1]); - Assert.False(equal[0, 2]); - Assert.False(equal[1, 0]); - Assert.True(equal[1, 1]); - Assert.False(equal[1, 2]); - Assert.False(equal[2, 0]); - Assert.False(equal[2, 1]); - Assert.True(equal[2, 2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); - equal = Tensor.SequenceEqual(t0, t1); - - Assert.Equal([3, 3], equal.Lengths.ToArray()); - Assert.True(equal[0, 0]); - Assert.False(equal[0, 1]); - Assert.False(equal[0, 2]); - Assert.False(equal[1, 0]); - Assert.True(equal[1, 1]); - Assert.False(equal[1, 2]); - Assert.False(equal[2, 0]); - Assert.False(equal[2, 1]); - Assert.True(equal[2, 2]); - - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 4)); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - Assert.Throws(() => Tensor.SequenceEqual(t0, t1)); - } + //[Fact] + //public static void TensorSequenceEqualTests() + //{ + // Tensor t0 = Tensor.Create(Enumerable.Range(0, 3), default); + // Tensor t1 = Tensor.Create(Enumerable.Range(0, 3), default); + // Tensor equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([3], equal.Lengths.ToArray()); + // Assert.True(equal[0]); + // Assert.True(equal[1]); + // Assert.True(equal[2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 3), [1, 3]); + // t1 = Tensor.Create(Enumerable.Range(0, 3), default); + // equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([1, 3], equal.Lengths.ToArray()); + // Assert.True(equal[0, 0]); + // Assert.True(equal[0, 1]); + // Assert.True(equal[0, 2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 3), [1, 1, 3]); + // t1 = Tensor.Create(Enumerable.Range(0, 3), default); + // equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([1, 1, 3], equal.Lengths.ToArray()); + // Assert.True(equal[0, 0, 0]); + // Assert.True(equal[0, 0, 1]); + // Assert.True(equal[0, 0, 2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 3), default); + // t1 = Tensor.Create(Enumerable.Range(0, 3), [1, 3]); + // equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([1, 3], equal.Lengths.ToArray()); + // Assert.True(equal[0, 0]); + // Assert.True(equal[0, 1]); + // Assert.True(equal[0, 2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 3), default); + // t1 = Tensor.Create(Enumerable.Range(0, 3), [3, 1]); + // equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([3, 3], equal.Lengths.ToArray()); + // Assert.True(equal[0, 0]); + // Assert.False(equal[0, 1]); + // Assert.False(equal[0, 2]); + // Assert.False(equal[1, 0]); + // Assert.True(equal[1, 1]); + // Assert.False(equal[1, 2]); + // Assert.False(equal[2, 0]); + // Assert.False(equal[2, 1]); + // Assert.True(equal[2, 2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 3), [1, 3]); + // t1 = Tensor.Create(Enumerable.Range(0, 3), [3, 1]); + // equal = Tensor.SequenceEqual(t0, t1); + + // Assert.Equal([3, 3], equal.Lengths.ToArray()); + // Assert.True(equal[0, 0]); + // Assert.False(equal[0, 1]); + // Assert.False(equal[0, 2]); + // Assert.False(equal[1, 0]); + // Assert.True(equal[1, 1]); + // Assert.False(equal[1, 2]); + // Assert.False(equal[2, 0]); + // Assert.False(equal[2, 1]); + // Assert.True(equal[2, 2]); + + // t0 = Tensor.Create(Enumerable.Range(0, 4), default); + // t1 = Tensor.Create(Enumerable.Range(0, 3), default); + // Assert.Throws(() => Tensor.SequenceEqual(t0, t1)); + //} [Fact] public static void TensorMultiplyTests() { - Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 3), default); + Tensor t1 = Tensor.Create(Enumerable.Range(0, 3), [3, 1]); Tensor t2 = Tensor.Multiply(t0, t1); Assert.Equal([3,3], t2.Lengths.ToArray()); @@ -695,7 +640,7 @@ public static void TensorMultiplyTests() Assert.Equal(2, t2[2, 1]); Assert.Equal(4, t2[2, 2]); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 9)).Reshape(3, 3); + t1 = Tensor.Create(Enumerable.Range(0, 9), [3, 3]); t2 = Tensor.Multiply(t0, t1); Assert.Equal([3, 3], t2.Lengths.ToArray()); @@ -708,17 +653,13 @@ public static void TensorMultiplyTests() Assert.Equal(0, t2[2, 0]); Assert.Equal(7, t2[2, 1]); Assert.Equal(16, t2[2, 2]); - - - - } [Fact] public static void TensorBroadcastTests() { - Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)), 1, 3, 1, 1, 1); - Tensor t1 = Tensor.Broadcast(t0, [1, 3, 1, 2, 1]); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 3), [1, 3, 1, 1, 1]); + Tensor t1 = Tensor.Broadcast(t0, [1, 3, 1, 2, 1]); Assert.Equal([1, 3, 1, 2, 1], t1.Lengths.ToArray()); @@ -729,7 +670,7 @@ public static void TensorBroadcastTests() Assert.Equal(2, t1[0, 2, 0, 0, 0]); Assert.Equal(2, t1[0, 2, 0, 1, 0]); - t1 = Tensor.Broadcast(t0, [1, 3, 2, 1, 1]); + t1 = Tensor.Broadcast(t0, [1, 3, 2, 1, 1]); Assert.Equal([1, 3, 2, 1, 1], t1.Lengths.ToArray()); Assert.Equal(0, t1[0, 0, 0, 0, 0]); @@ -739,9 +680,9 @@ public static void TensorBroadcastTests() Assert.Equal(2, t1[0, 2, 0, 0, 0]); Assert.Equal(2, t1[0, 2, 1, 0, 0]); - t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(1, 3); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); - var t2 = Tensor.Broadcast(t0, [3, 3]); + t0 = Tensor.Create(Enumerable.Range(0, 3), [1, 3]); + t1 = Tensor.Create(Enumerable.Range(0, 3), [3, 1]); + var t2 = Tensor.Broadcast(t0, [3, 3]); Assert.Equal([3, 3], t2.Lengths.ToArray()); Assert.Equal(0, t2[0, 0]); @@ -754,8 +695,8 @@ public static void TensorBroadcastTests() Assert.Equal(1, t2[2, 1]); Assert.Equal(2, t2[2, 2]); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)).Reshape(3, 1); - t2 = Tensor.Broadcast(t1, [3, 3]); + t1 = Tensor.Create(Enumerable.Range(0, 3), [3, 1]); + t2 = Tensor.Broadcast(t1, [3, 3]); Assert.Equal([3, 3], t2.Lengths.ToArray()); Assert.Equal(0, t2[0, 0]); @@ -782,8 +723,8 @@ public static void TensorBroadcastTests() var t3 = t2.Slice(0..1, ..); Assert.Equal([1, 3], t3.Lengths.ToArray()); - t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 3)); - t2 = Tensor.Broadcast(t1, [3, 3]); + t1 = Tensor.Create(Enumerable.Range(0, 3), default); + t2 = Tensor.Broadcast(t1, [3, 3]); Assert.Equal([3, 3], t2.Lengths.ToArray()); Assert.Equal(0, t2[0, 0]); @@ -797,29 +738,10 @@ public static void TensorBroadcastTests() Assert.Equal(2, t2[2, 2]); } - //// Needs internals visible - //[Fact] - //public static void TensorBroadcastToShapeCompatibleTests() - //{ - // Tensor t0 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 8); - // Tensor t1 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 1, 8); - - // Assert.True(Tensor.AreShapesBroadcastToCompatible(t0.Lengths, t1.Lengths)); - // Assert.True(Tensor.AreShapesBroadcastToCompatible(t0, t1)); - - // t1 = Tensor.Reshape(Tensor.FillRange(Enumerable.Range(0, 8)), 2, 4); - // Assert.False(Tensor.AreShapesBroadcastToCompatible(t0, t1)); - - // t0 = Tensor.FillRange(Enumerable.Range(0, 3)); - - // Assert.False(Tensor.AreShapesBroadcastToCompatible(t0.Lengths, [1,3,1,1,1])); - - //} - [Fact] public static void TensorResizeTests() { - Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 8), [2, 2, 2]); var t1 = Tensor.Resize(t0, [1]); Assert.Equal([1], t1.Lengths.ToArray()); Assert.Equal(0, t1[0]); @@ -867,8 +789,8 @@ public static void TensorResizeTests() [Fact] public static void TensorSplitTests() { - Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); - var t1 = Tensor.Split(t0, 2, 0); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 8), [2, 2, 2]); + var t1 = Tensor.Split(t0, 2, 0); Assert.Equal([1, 2, 2], t1[0].Lengths.ToArray()); Assert.Equal([1, 2, 2], t1[1].Lengths.ToArray()); Assert.Equal(0, t1[0][0, 0, 0]); @@ -880,7 +802,7 @@ public static void TensorSplitTests() Assert.Equal(6, t1[1][0, 1, 0]); Assert.Equal(7, t1[1][0, 1, 1]); - t1 = Tensor.Split(t0, 2, 1); + t1 = Tensor.Split(t0, 2, 1); Assert.Equal([2, 1, 2], t1[0].Lengths.ToArray()); Assert.Equal([2, 1, 2], t1[1].Lengths.ToArray()); Assert.Equal(0, t1[0][0, 0, 0]); @@ -892,7 +814,7 @@ public static void TensorSplitTests() Assert.Equal(6, t1[1][1, 0, 0]); Assert.Equal(7, t1[1][1, 0, 1]); - t1 = Tensor.Split(t0, 2, 2); + t1 = Tensor.Split(t0, 2, 2); Assert.Equal([2, 2, 1], t1[0].Lengths.ToArray()); Assert.Equal([2, 2, 1], t1[1].Lengths.ToArray()); Assert.Equal(0, t1[0][0, 0, 0]); @@ -908,8 +830,8 @@ public static void TensorSplitTests() [Fact] public static void TensorReverseTests() { - Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 8)), 2, 2, 2); - var t1 = Tensor.Reverse(t0); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 8), [2, 2, 2]); + var t1 = Tensor.Reverse(t0); Assert.Equal(7, t1[0, 0, 0]); Assert.Equal(6, t1[0, 0, 1]); Assert.Equal(5, t1[0, 1, 0]); @@ -919,7 +841,7 @@ public static void TensorReverseTests() Assert.Equal(1, t1[1, 1, 0]); Assert.Equal(0, t1[1, 1, 1]); - t1 = Tensor.Reverse(t0, 0); + t1 = Tensor.Reverse(t0, 0); Assert.Equal(4, t1[0, 0, 0]); Assert.Equal(5, t1[0, 0, 1]); Assert.Equal(6, t1[0, 1, 0]); @@ -929,7 +851,7 @@ public static void TensorReverseTests() Assert.Equal(2, t1[1, 1, 0]); Assert.Equal(3, t1[1, 1, 1]); - t1 = Tensor.Reverse(t0, 1); + t1 = Tensor.Reverse(t0, 1); Assert.Equal(2, t1[0, 0, 0]); Assert.Equal(3, t1[0, 0, 1]); Assert.Equal(0, t1[0, 1, 0]); @@ -939,7 +861,7 @@ public static void TensorReverseTests() Assert.Equal(4, t1[1, 1, 0]); Assert.Equal(5, t1[1, 1, 1]); - t1 = Tensor.Reverse(t0, 2); + t1 = Tensor.Reverse(t0, 2); Assert.Equal(1, t1[0, 0, 0]); Assert.Equal(0, t1[0, 0, 1]); Assert.Equal(3, t1[0, 1, 0]); @@ -953,8 +875,8 @@ public static void TensorReverseTests() [Fact] public static void TensorSetSliceTests() { - Tensor t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); - Tensor t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 10)), 2, 5); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 10), [2, 5]); + Tensor t1 = Tensor.Create(Enumerable.Range(10, 10), [2, 5]); Tensor.SetSlice(t0, t1); Assert.Equal(10, t0[0, 0]); @@ -968,8 +890,8 @@ public static void TensorSetSliceTests() Assert.Equal(18, t0[1, 3]); Assert.Equal(19, t0[1, 4]); - t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); - t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 5)), 1, 5); + t0 = Tensor.Create(Enumerable.Range(0, 10), [2, 5]); + t1 = Tensor.Create(Enumerable.Range(10, 5), [1, 5]); t0.SetSlice(t1, 0..1, ..); Assert.Equal(10, t0[0, 0]); @@ -983,8 +905,8 @@ public static void TensorSetSliceTests() Assert.Equal(8, t0[1, 3]); Assert.Equal(9, t0[1, 4]); - t0 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)), 2, 5); - t1 = Tensor.Reshape(Tensor.CreateFromEnumerable(Enumerable.Range(10, 5)), 1, 5); + t0 = Tensor.Create(Enumerable.Range(0, 10), [2, 5]); + t1 = Tensor.Create(Enumerable.Range(10, 5), [1, 5]); Tensor.SetSlice(t0, t1, 1..2, ..); Assert.Equal(0, t0[0, 0]); @@ -1001,8 +923,8 @@ public static void TensorSetSliceTests() [Fact] public static void TensorStackTests() { - Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)).Reshape(2, 5); - Tensor t1 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 10)).Reshape(2, 5); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 10), [2, 5]); + Tensor t1 = Tensor.Create(Enumerable.Range(0, 10), [2, 5]); var resultTensor = Tensor.Stack([t0, t1]); Assert.Equal(3, resultTensor.Rank); @@ -1089,12 +1011,9 @@ public static void TensorStackTests() [Fact] public static void TensorStdDevTests() { - Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); - //Tensor.Sum(t0) - - Assert.Equal(StdDev([0, 1, 2, 3]), Tensor.StdDev(t0), .1); - + Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); + Assert.Equal(StdDev([0, 1, 2, 3]), Tensor.StdDev(t0), .1); } public static float StdDev(float[] values) @@ -1111,9 +1030,9 @@ public static float StdDev(float[] values) [Fact] public static void TensorMeanTests() { - Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); - Assert.Equal(Mean([0, 1, 2, 3]), Tensor.Mean(t0), .1); + Assert.Equal(Mean([0, 1, 2, 3]), Tensor.Mean(t0), .1); } public static float Mean(float[] values) @@ -1129,8 +1048,8 @@ public static float Mean(float[] values) [Fact] public static void TensorConcatenateTests() { - Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); - Tensor t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); + Tensor t1 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); var resultTensor = Tensor.Concatenate([t0, t1]); Assert.Equal(2, resultTensor.Rank); @@ -1170,7 +1089,7 @@ public static void TensorConcatenateTests() Assert.Equal(2, resultTensor[6]); Assert.Equal(3, resultTensor[7]); - Tensor t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t2 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); resultTensor = Tensor.Concatenate([t0, t1, t2]); Assert.Equal(2, resultTensor.Rank); @@ -1224,9 +1143,9 @@ public static void TensorConcatenateTests() Assert.Equal(2, resultTensor[1, 4]); Assert.Equal(3, resultTensor[1, 5]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 3, 2); - t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 3, 2); - t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 3, 2]); + t1 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 3, 2]); + t2 = Tensor.Create((Enumerable.Range(0, 8).Select(i => (float)i)), [2, 2, 2]); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2])); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 2)); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 5)); @@ -1251,9 +1170,9 @@ public static void TensorConcatenateTests() Helpers.AdjustIndices(resultTensor.Rank - 1, 1, ref indices, resultTensor.Lengths); } - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); - t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); - t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 2, 3]); + t1 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 2, 3]); + t2 = Tensor.Create((Enumerable.Range(0, 8).Select(i => (float)i)), [2, 2, 2]); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 0)); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 1)); resultTensor = Tensor.Concatenate([t0, t1, t2], 2); @@ -1270,9 +1189,9 @@ public static void TensorConcatenateTests() Helpers.AdjustIndices(resultTensor.Rank - 1, 1, ref indices, resultTensor.Lengths); } - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(3, 2, 2); - t1 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(3, 2, 2); - t2 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 8).Select(i => (float)i))).Reshape(2, 2, 2); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [3, 2, 2]); + t1 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [3, 2, 2]); + t2 = Tensor.Create((Enumerable.Range(0, 8).Select(i => (float)i)), [2, 2, 2]); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 1)); Assert.Throws(() => Tensor.Concatenate([t0, t1, t2], 2)); resultTensor = Tensor.Concatenate([t0, t1, t2]); @@ -1293,7 +1212,7 @@ public static void TensorConcatenateTests() [Fact] public static void TensorTransposeTests() { - Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); var t1 = Tensor.Permute(t0); Assert.Equal(0, t1[0, 0]); @@ -1301,7 +1220,7 @@ public static void TensorTransposeTests() Assert.Equal(1, t1[1, 0]); Assert.Equal(3, t1[1, 1]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 6).Select(i => (float)i))).Reshape(2, 3); + t0 = Tensor.Create((Enumerable.Range(0, 6).Select(i => (float)i)), [2, 3]); t1 = Tensor.Permute(t0); Assert.Equal(3, t1.Lengths[0]); @@ -1313,7 +1232,7 @@ public static void TensorTransposeTests() Assert.Equal(2, t1[2, 0]); Assert.Equal(5, t1[2, 1]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 6).Select(i => (float)i))).Reshape(1, 2, 3); + t0 = Tensor.Create((Enumerable.Range(0, 6).Select(i => (float)i)), [1, 2, 3]); t1 = Tensor.Permute(t0); Assert.Equal(3, t1.Lengths[0]); @@ -1326,7 +1245,7 @@ public static void TensorTransposeTests() Assert.Equal(2, t1[2, 0, 0]); Assert.Equal(5, t1[2, 1, 0]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 2, 3]); t1 = Tensor.Permute(t0); Assert.Equal(3, t1.Lengths[0]); @@ -1345,7 +1264,7 @@ public static void TensorTransposeTests() Assert.Equal(5, t1[2, 1, 0]); Assert.Equal(11, t1[2, 1, 1]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 2, 3]); t1 = Tensor.Permute(t0, 1, 2, 0); Assert.Equal(2, t1.Lengths[0]); @@ -1368,7 +1287,7 @@ public static void TensorTransposeTests() [Fact] public static void TensorPermuteTests() { - Tensor t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 4).Select(i => (float)i))).Reshape(2, 2); + Tensor t0 = Tensor.Create((Enumerable.Range(0, 4).Select(i => (float)i)), [2, 2]); var t1 = Tensor.Transpose(t0); Assert.Equal(0, t1[0, 0]); @@ -1376,7 +1295,7 @@ public static void TensorPermuteTests() Assert.Equal(1, t1[1, 0]); Assert.Equal(3, t1[1, 1]); - t0 = Tensor.CreateFromEnumerable((Enumerable.Range(0, 12).Select(i => (float)i))).Reshape(2, 2, 3); + t0 = Tensor.Create((Enumerable.Range(0, 12).Select(i => (float)i)), [2, 2, 3]); t1 = Tensor.Transpose(t0); Assert.Equal(2, t1.Lengths[0]); @@ -2136,7 +2055,7 @@ public static void TensorUnsqueezeTest() Assert.Throws(() => Tensor.Unsqueeze(tensor, -1)); Assert.Throws(() => Tensor.Unsqueeze(tensor, 2)); - Tensor t0 = Tensor.CreateFromEnumerable(Enumerable.Range(0, 2)); + Tensor t0 = Tensor.Create(Enumerable.Range(0, 2), default); t0 = Tensor.Unsqueeze(t0, 1); Assert.Equal(0, t0[0, 0]); Assert.Equal(1, t0[1, 0]);