From 85259f64b346f2064b52b2a2f408a7def913b8c8 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Tue, 5 Sep 2023 06:44:21 -0700 Subject: [PATCH] Adding a naive implementation of various primitive tensor operations (#91228) * Adding a naive implementation of various primitive tensor operations * Adding tests covering the new tensor primitives APIs * Adding tensor primitives APIs to the ref assembly * Allow .NET Framework to build/run * Sync TFMs between ref and src, csproj simplication and clean-up * Apply suggestions from code review Co-authored-by: Viktor Hofer * Don't use var * Fix the S.N.Tensors readme and remove the file marking it as non-shipping --------- Co-authored-by: Viktor Hofer Co-authored-by: Michael Sharp <51342856+michaelgsharp@users.noreply.github.com> --- .../Directory.Build.props | 8 - .../System.Numerics.Tensors/README.md | 3 +- .../ref/System.Numerics.Tensors.cs | 166 +- .../ref/System.Numerics.Tensors.csproj | 2 + .../src/Properties/InternalsVisibleTo.cs | 6 - .../src/Resources/Strings.resx | 50 +- .../src/System.Numerics.Tensors.csproj | 30 +- .../Numerics/Tensors/ArrayTensorExtensions.cs | 149 - .../System/Numerics/Tensors/ArrayUtilities.cs | 216 - .../Tensors/CompressedSparseTensor.cs | 517 - .../System/Numerics/Tensors/DenseTensor.cs | 178 - .../System/Numerics/Tensors/SparseTensor.cs | 177 - .../src/System/Numerics/Tensors/Tensor.cs | 1365 -- .../Numerics/Tensors/TensorPrimitives.cs | 467 + .../src/System/ThrowHelper.cs | 32 + .../tests/NativeMemory.cs | 108 - .../System.Numerics.Tensors.Tests.csproj | 36 +- .../tests/TensorArithmetic.cs | 16165 ---------------- .../tests/TensorArithmetic.tt | 237 - .../tests/TensorExtensions.cs | 31 - .../tests/TensorOperations.cs | 738 - .../tests/TensorOperations.tt | 239 - .../tests/TensorPrimitivesTests.cs | 633 + .../tests/TensorTemplate.ttinclude | 328 - .../tests/TensorTests.cs | 2486 --- .../tests/TensorTestsBase.cs | 187 - 26 files changed, 1181 insertions(+), 23373 deletions(-) delete mode 100644 src/libraries/System.Numerics.Tensors/Directory.Build.props delete mode 100644 src/libraries/System.Numerics.Tensors/src/Properties/InternalsVisibleTo.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayTensorExtensions.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayUtilities.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/CompressedSparseTensor.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/DenseTensor.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs delete mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/Tensor.cs create mode 100644 src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs create mode 100644 src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/NativeMemory.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.tt delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorExtensions.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorOperations.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorOperations.tt create mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorPrimitivesTests.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorTemplate.ttinclude delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorTests.cs delete mode 100644 src/libraries/System.Numerics.Tensors/tests/TensorTestsBase.cs diff --git a/src/libraries/System.Numerics.Tensors/Directory.Build.props b/src/libraries/System.Numerics.Tensors/Directory.Build.props deleted file mode 100644 index 36078bccbf7aa..0000000000000 --- a/src/libraries/System.Numerics.Tensors/Directory.Build.props +++ /dev/null @@ -1,8 +0,0 @@ - - - - - true - false - - \ No newline at end of file diff --git a/src/libraries/System.Numerics.Tensors/README.md b/src/libraries/System.Numerics.Tensors/README.md index 026563de81306..6190da60e77c5 100644 --- a/src/libraries/System.Numerics.Tensors/README.md +++ b/src/libraries/System.Numerics.Tensors/README.md @@ -1,2 +1,3 @@ # System.Numerics.Tensors -This library has not been shipped publicly and is not accepting contributions at this time. \ No newline at end of file + +Provides APIs for performing primitive operations over tensors represented by spans of memory. diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.cs b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.cs index 3161a4c7e780c..c657a43a054dd 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.cs +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.cs @@ -6,151 +6,27 @@ namespace System.Numerics.Tensors { - public static partial class ArrayTensorExtensions + public static class TensorPrimitives { - public static System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor(this System.Array array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor(this T[,,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor(this T[,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor(this T[] array) { throw null; } - public static System.Numerics.Tensors.SparseTensor ToSparseTensor(this System.Array array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.SparseTensor ToSparseTensor(this T[,,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.SparseTensor ToSparseTensor(this T[,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.SparseTensor ToSparseTensor(this T[] array) { throw null; } - public static System.Numerics.Tensors.DenseTensor ToTensor(this System.Array array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.DenseTensor ToTensor(this T[,,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.DenseTensor ToTensor(this T[,] array, bool reverseStride = false) { throw null; } - public static System.Numerics.Tensors.DenseTensor ToTensor(this T[] array) { throw null; } - } - public partial class CompressedSparseTensor : System.Numerics.Tensors.Tensor - { - public CompressedSparseTensor(System.Memory values, System.Memory compressedCounts, System.Memory indices, int nonZeroCount, System.ReadOnlySpan dimensions, bool reverseStride = false) : base (default(System.Array), default(bool)) { } - public CompressedSparseTensor(System.ReadOnlySpan dimensions, bool reverseStride = false) : base (default(System.Array), default(bool)) { } - public CompressedSparseTensor(System.ReadOnlySpan dimensions, int capacity, bool reverseStride = false) : base (default(System.Array), default(bool)) { } - public int Capacity { get { throw null; } } - public System.Memory CompressedCounts { get { throw null; } } - public System.Memory Indices { get { throw null; } } - public override T this[System.ReadOnlySpan indices] { get { throw null; } set { } } - public int NonZeroCount { get { throw null; } } - public System.Memory Values { get { throw null; } } - public override System.Numerics.Tensors.Tensor Clone() { throw null; } - public override System.Numerics.Tensors.Tensor CloneEmpty(System.ReadOnlySpan dimensions) { throw null; } - public override T GetValue(int index) { throw null; } - public override System.Numerics.Tensors.Tensor Reshape(System.ReadOnlySpan dimensions) { throw null; } - public override void SetValue(int index, T value) { } - public override System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor() { throw null; } - public override System.Numerics.Tensors.DenseTensor ToDenseTensor() { throw null; } - public override System.Numerics.Tensors.SparseTensor ToSparseTensor() { throw null; } - } - public partial class DenseTensor : System.Numerics.Tensors.Tensor - { - public DenseTensor(int length) : base (default(System.Array), default(bool)) { } - public DenseTensor(System.Memory memory, System.ReadOnlySpan dimensions, bool reverseStride = false) : base (default(System.Array), default(bool)) { } - public DenseTensor(System.ReadOnlySpan dimensions, bool reverseStride = false) : base (default(System.Array), default(bool)) { } - public System.Memory Buffer { get { throw null; } } - public override System.Numerics.Tensors.Tensor Clone() { throw null; } - public override System.Numerics.Tensors.Tensor CloneEmpty(System.ReadOnlySpan dimensions) { throw null; } - protected override void CopyTo(T[] array, int arrayIndex) { } - public override T GetValue(int index) { throw null; } - protected override int IndexOf(T item) { throw null; } - public override System.Numerics.Tensors.Tensor Reshape(System.ReadOnlySpan dimensions) { throw null; } - public override void SetValue(int index, T value) { } - } - public partial class SparseTensor : System.Numerics.Tensors.Tensor - { - public SparseTensor(System.ReadOnlySpan dimensions, bool reverseStride = false, int capacity = 0) : base (default(System.Array), default(bool)) { } - public int NonZeroCount { get { throw null; } } - public override System.Numerics.Tensors.Tensor Clone() { throw null; } - public override System.Numerics.Tensors.Tensor CloneEmpty(System.ReadOnlySpan dimensions) { throw null; } - public override T GetValue(int index) { throw null; } - public override System.Numerics.Tensors.Tensor Reshape(System.ReadOnlySpan dimensions) { throw null; } - public override void SetValue(int index, T value) { } - public override System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor() { throw null; } - public override System.Numerics.Tensors.DenseTensor ToDenseTensor() { throw null; } - public override System.Numerics.Tensors.SparseTensor ToSparseTensor() { throw null; } - } - public static partial class Tensor - { - public static System.Numerics.Tensors.Tensor CreateFromDiagonal(System.Numerics.Tensors.Tensor diagonal) { throw null; } - public static System.Numerics.Tensors.Tensor CreateFromDiagonal(System.Numerics.Tensors.Tensor diagonal, int offset) { throw null; } - public static System.Numerics.Tensors.Tensor CreateIdentity(int size) { throw null; } - public static System.Numerics.Tensors.Tensor CreateIdentity(int size, bool columMajor) { throw null; } - public static System.Numerics.Tensors.Tensor CreateIdentity(int size, bool columMajor, T oneValue) { throw null; } - } - public abstract partial class Tensor : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable - { - protected Tensor(System.Array fromArray, bool reverseStride) { } - protected Tensor(int length) { } - protected Tensor(System.ReadOnlySpan dimensions, bool reverseStride) { } - public System.ReadOnlySpan Dimensions { get { throw null; } } - public bool IsFixedSize { get { throw null; } } - public bool IsReadOnly { get { throw null; } } - public bool IsReversedStride { get { throw null; } } - public virtual T this[params int[] indices] { get { throw null; } set { } } - public virtual T this[System.ReadOnlySpan indices] { get { throw null; } set { } } - public long Length { get { throw null; } } - public int Rank { get { throw null; } } - public System.ReadOnlySpan Strides { get { throw null; } } - int System.Collections.Generic.ICollection.Count { get { throw null; } } - T System.Collections.Generic.IList.this[int index] { get { throw null; } set { } } - int System.Collections.Generic.IReadOnlyCollection.Count { get { throw null; } } - T System.Collections.Generic.IReadOnlyList.this[int index] { get { throw null; } } - int System.Collections.ICollection.Count { get { throw null; } } - bool System.Collections.ICollection.IsSynchronized { get { throw null; } } - object System.Collections.ICollection.SyncRoot { get { throw null; } } - object? System.Collections.IList.this[int index] { get { throw null; } set { } } - public abstract System.Numerics.Tensors.Tensor Clone(); - public virtual System.Numerics.Tensors.Tensor CloneEmpty() { throw null; } - public virtual System.Numerics.Tensors.Tensor CloneEmpty(System.ReadOnlySpan dimensions) { throw null; } - public virtual System.Numerics.Tensors.Tensor CloneEmpty() { throw null; } - public abstract System.Numerics.Tensors.Tensor CloneEmpty(System.ReadOnlySpan dimensions); - public static int Compare(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) { throw null; } - protected virtual bool Contains(T item) { throw null; } - protected virtual void CopyTo(T[] array, int arrayIndex) { } - public static bool Equals(System.Numerics.Tensors.Tensor left, System.Numerics.Tensors.Tensor right) { throw null; } - public virtual void Fill(T value) { } - public string GetArrayString(bool includeWhitespace = true) { throw null; } - public System.Numerics.Tensors.Tensor GetDiagonal() { throw null; } - public System.Numerics.Tensors.Tensor GetDiagonal(int offset) { throw null; } - public System.Numerics.Tensors.Tensor GetTriangle() { throw null; } - public System.Numerics.Tensors.Tensor GetTriangle(int offset) { throw null; } - public System.Numerics.Tensors.Tensor GetUpperTriangle() { throw null; } - public System.Numerics.Tensors.Tensor GetUpperTriangle(int offset) { throw null; } - public abstract T GetValue(int index); - protected virtual int IndexOf(T item) { throw null; } - public abstract System.Numerics.Tensors.Tensor Reshape(System.ReadOnlySpan dimensions); - public abstract void SetValue(int index, T value); - public struct Enumerator : System.Collections.Generic.IEnumerator - { - public T Current { get; private set; } - object? System.Collections.IEnumerator.Current => throw null; - public bool MoveNext() => throw null; - public void Reset() { } - public void Dispose() { } - } - public Enumerator GetEnumerator() => throw null; - void System.Collections.Generic.ICollection.Add(T item) { } - void System.Collections.Generic.ICollection.Clear() { } - bool System.Collections.Generic.ICollection.Contains(T item) { throw null; } - void System.Collections.Generic.ICollection.CopyTo(T[] array, int arrayIndex) { } - bool System.Collections.Generic.ICollection.Remove(T item) { throw null; } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.Generic.IList.IndexOf(T item) { throw null; } - void System.Collections.Generic.IList.Insert(int index, T item) { } - void System.Collections.Generic.IList.RemoveAt(int index) { } - void System.Collections.ICollection.CopyTo(System.Array array, int index) { } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - int System.Collections.IList.Add(object? value) { throw null; } - void System.Collections.IList.Clear() { } - bool System.Collections.IList.Contains(object? value) { throw null; } - int System.Collections.IList.IndexOf(object? value) { throw null; } - void System.Collections.IList.Insert(int index, object? value) { } - void System.Collections.IList.Remove(object? value) { } - void System.Collections.IList.RemoveAt(int index) { } - int System.Collections.IStructuralComparable.CompareTo(object? other, System.Collections.IComparer comparer) { throw null; } - bool System.Collections.IStructuralEquatable.Equals(object? other, System.Collections.IEqualityComparer comparer) { throw null; } - int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; } - public virtual System.Numerics.Tensors.CompressedSparseTensor ToCompressedSparseTensor() { throw null; } - public virtual System.Numerics.Tensors.DenseTensor ToDenseTensor() { throw null; } - public virtual System.Numerics.Tensors.SparseTensor ToSparseTensor() { throw null; } + public static void Add(System.ReadOnlySpan x, float y, System.Span destination) { throw null; } + public static void Add(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) { throw null; } + public static void AddMultiply(System.ReadOnlySpan x, float y, System.ReadOnlySpan multiplier, System.Span destination) { throw null; } + public static void AddMultiply(System.ReadOnlySpan x, System.ReadOnlySpan y, float multiplier, System.Span destination) { throw null; } + public static void AddMultiply(System.ReadOnlySpan x, System.ReadOnlySpan y, System.ReadOnlySpan multiplier, System.Span destination) { throw null; } + public static void Cosh(System.ReadOnlySpan x, System.Span destination) { throw null; } + public static void Divide(System.ReadOnlySpan x, float y, System.Span destination) { throw null; } + public static void Divide(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) { throw null; } + public static void Exp(System.ReadOnlySpan x, System.Span destination) { throw null; } + public static void Log(System.ReadOnlySpan x, System.Span destination) { throw null; } + public static void Multiply(System.ReadOnlySpan x, float y, System.Span destination) { throw null; } + public static void Multiply(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) { throw null; } + public static void MultiplyAdd(System.ReadOnlySpan x, float y, System.ReadOnlySpan addend, System.Span destination) { throw null; } + public static void MultiplyAdd(System.ReadOnlySpan x, System.ReadOnlySpan y, float addend, System.Span destination) { throw null; } + public static void MultiplyAdd(System.ReadOnlySpan x, System.ReadOnlySpan y, System.ReadOnlySpan addend, System.Span destination) { throw null; } + public static void Negate(System.ReadOnlySpan x, System.Span destination) { throw null; } + public static void Subtract(System.ReadOnlySpan x, float y, System.Span destination) { throw null; } + public static void Subtract(System.ReadOnlySpan x, System.ReadOnlySpan y, System.Span destination) { throw null; } + public static void Sinh(System.ReadOnlySpan x, System.Span destination) { throw null; } + public static void Tanh(System.ReadOnlySpan x, System.Span destination) { throw null; } } } diff --git a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj index cabfe50e267cf..8d1d484b33ecd 100644 --- a/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj @@ -1,4 +1,5 @@ + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) @@ -10,4 +11,5 @@ + \ No newline at end of file diff --git a/src/libraries/System.Numerics.Tensors/src/Properties/InternalsVisibleTo.cs b/src/libraries/System.Numerics.Tensors/src/Properties/InternalsVisibleTo.cs deleted file mode 100644 index 2b044e474d570..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/Properties/InternalsVisibleTo.cs +++ /dev/null @@ -1,6 +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.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("System.Numerics.Tensors.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] diff --git a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx index 57f792dde51dc..f9f7f45078a04 100644 --- a/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx +++ b/src/libraries/System.Numerics.Tensors/src/Resources/Strings.resx @@ -117,52 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Array must contain elements. + + Destination is too short. - - Cannot compare {0} to {1}. - - - Cannot compare {0} to {1} with different dimension {2}, {3} != {4}. - - - Cannot compare {0} with different dimension {1}, {2} != {3}. - - - Cannot compare {0} with Rank {1} to {2} with Rank {3}. - - - Cannot compute diagonal of {0} with Rank less than 2. - - - Cannot compute diagonal with offset {0}. - - - Tensor {0} must have at least one dimension. - - - Cannot compute triangle of {0} with Rank less than 2. - - - Cannot reshape array due to mismatch in lengths, currently {0} would become {1}. - - - Dimensions must be positive and non-zero. - - - Dimensions must contain elements. - - - Length of {0} ({1}) must match product of {2} ({3}). - - - The number of elements in the Tensor is greater than the available space from index to the end of the destination array. - - - Only single dimensional arrays are supported for the requested action. - - - The value "{0}" is not of type "{1}" and cannot be used in this generic collection. + + Length of '{0}' must be same as length of '{1}'. \ No newline at end of file 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 521f8055a4fa6..5c188c2e0b841 100644 --- a/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj +++ b/src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj @@ -1,30 +1,28 @@ + $(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true - - $(NoWarn);1591 true - Tensor class which represents and extends multi-dimensional arrays. - -Commonly Used Types: -System.Numerics.Tensors.Tensor<T> -System.Numerics.Tensors.CompressedSparseTensor<T> -System.Numerics.Tensors.DenseTensor<T> -System.Numerics.Tensors.SparseTensor<T> + Provides support for operating over tensors. + + true - - - - - - - + + + + + + + + diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayTensorExtensions.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayTensorExtensions.cs deleted file mode 100644 index 05e12a62c990e..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayTensorExtensions.cs +++ /dev/null @@ -1,149 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - public static class ArrayTensorExtensions - { - /// - /// Creates a copy of this single-dimensional array as a DenseTensor<T> - /// - /// Type contained in the array to copy to the DenseTensor<T>. - /// The array to create a DenseTensor<T> from. - /// A 1-dimensional DenseTensor<T> with the same length and content as . - public static DenseTensor ToTensor(this T[] array) - { - return new DenseTensor(array); - } - - /// - /// Creates a copy of this two-dimensional array as a DenseTensor<T> - /// - /// Type contained in the array to copy to the DenseTensor<T>. - /// The array to create a DenseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): row-major. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): column-major. - /// A 2-dimensional DenseTensor<T> with the same dimensions and content as . - public static DenseTensor ToTensor(this T[,] array, bool reverseStride = false) - { - return new DenseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this three-dimensional array as a DenseTensor<T> - /// - /// Type contained in the array to copy to the DenseTensor<T>. - /// The array to create a DenseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A 3-dimensional DenseTensor<T> with the same dimensions and content as . - public static DenseTensor ToTensor(this T[,,] array, bool reverseStride = false) - { - return new DenseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this n-dimensional array as a DenseTensor<T> - /// - /// Type contained in the array to copy to the DenseTensor<T>. - /// The array to create a DenseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A n-dimensional DenseTensor<T> with the same dimensions and content as . - public static DenseTensor ToTensor(this Array array, bool reverseStride = false) - { - return new DenseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this single-dimensional array as a SparseTensor<T> - /// - /// Type contained in the array to copy to the SparseTensor<T>. - /// The array to create a SparseTensor<T> from. - /// A 1-dimensional SparseTensor<T> with the same length and content as . - public static SparseTensor ToSparseTensor(this T[] array) - { - return new SparseTensor(array); - } - - /// - /// Creates a copy of this two-dimensional array as a SparseTensor<T> - /// - /// Type contained in the array to copy to the SparseTensor<T>. - /// The array to create a SparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): row-major. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): column-major. - /// A 2-dimensional SparseTensor<T> with the same dimensions and content as . - public static SparseTensor ToSparseTensor(this T[,] array, bool reverseStride = false) - { - return new SparseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this three-dimensional array as a SparseTensor<T> - /// - /// Type contained in the array to copy to the SparseTensor<T>. - /// The array to create a SparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A 3-dimensional SparseTensor<T> with the same dimensions and content as . - public static SparseTensor ToSparseTensor(this T[,,] array, bool reverseStride = false) - { - return new SparseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this n-dimensional array as a SparseTensor<T> - /// - /// Type contained in the array to copy to the SparseTensor<T>. - /// The array to create a SparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A n-dimensional SparseTensor<T> with the same dimensions and content as . - public static SparseTensor ToSparseTensor(this Array array, bool reverseStride = false) - { - return new SparseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this single-dimensional array as a CompressedSparseTensor<T> - /// - /// Type contained in the array to copy to the CompressedSparseTensor<T>. - /// The array to create a CompressedSparseTensor<T> from. - /// A 1-dimensional CompressedSparseTensor<T> with the same length and content as . - public static CompressedSparseTensor ToCompressedSparseTensor(this T[] array) - { - return new CompressedSparseTensor(array); - } - - /// - /// Creates a copy of this two-dimensional array as a CompressedSparseTensor<T> - /// - /// Type contained in the array to copy to the CompressedSparseTensor<T>. - /// The array to create a CompressedSparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): row-major. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): column-major. - /// A 2-dimensional CompressedSparseTensor<T> with the same dimensions and content as . - public static CompressedSparseTensor ToCompressedSparseTensor(this T[,] array, bool reverseStride = false) - { - return new CompressedSparseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this three-dimensional array as a CompressedSparseTensor<T> - /// - /// Type contained in the array to copy to the CompressedSparseTensor<T>. - /// The array to create a CompressedSparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A 3-dimensional CompressedSparseTensor<T> with the same dimensions and content as . - public static CompressedSparseTensor ToCompressedSparseTensor(this T[,,] array, bool reverseStride = false) - { - return new CompressedSparseTensor(array, reverseStride); - } - - /// - /// Creates a copy of this n-dimensional array as a CompressedSparseTensor<T> - /// - /// Type contained in the array to copy to the CompressedSparseTensor<T>. - /// The array to create a CompressedSparseTensor<T> from. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// A n-dimensional CompressedSparseTensor<T> with the same dimensions and content as . - public static CompressedSparseTensor ToCompressedSparseTensor(this Array array, bool reverseStride = false) - { - return new CompressedSparseTensor(array, reverseStride); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayUtilities.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayUtilities.cs deleted file mode 100644 index 97152090dfea0..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/ArrayUtilities.cs +++ /dev/null @@ -1,216 +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.Diagnostics; - -namespace System.Numerics.Tensors -{ - internal static class ArrayUtilities - { - public const int StackallocMax = 16; - - public static long GetProduct(ReadOnlySpan dimensions, int startIndex = 0) - { - if (dimensions.Length == 0) - { - return 0; - } - - long product = 1; - for (int i = startIndex; i < dimensions.Length; i++) - { - if (dimensions[i] < 0) - { - throw new ArgumentOutOfRangeException($"{nameof(dimensions)}[{i}]"); - } - - // we use a long which should be much larger than is ever used here, - // but still force checked - checked - { - product *= dimensions[i]; - } - } - - return product; - } - - public static bool IsAscending(ReadOnlySpan values) - { - for (int i = 1; i < values.Length; i++) - { - if (values[i] < values[i - 1]) - { - return false; - } - } - - return true; - } - - public static bool IsDescending(ReadOnlySpan values) - { - for (int i = 1; i < values.Length; i++) - { - if (values[i] > values[i - 1]) - { - return false; - } - } - - return true; - } - - /// - /// Gets the set of strides that can be used to calculate the offset of n-dimensions in a 1-dimensional layout - /// - /// - /// - /// - public static int[] GetStrides(ReadOnlySpan dimensions, bool reverseStride = false) - { - int[] strides = new int[dimensions.Length]; - - int stride = 1; - if (reverseStride) - { - for (int i = 0; i < strides.Length; i++) - { - strides[i] = stride; - stride *= dimensions[i]; - } - } - else - { - for (int i = strides.Length - 1; i >= 0; i--) - { - strides[i] = stride; - stride *= dimensions[i]; - } - } - - return strides; - } - - public static void SplitStrides(int[] strides, int[] splitAxes, int[] newStrides, int stridesOffset, int[] splitStrides, int splitStridesOffset) - { - int newStrideIndex = 0; - for (int i = 0; i < strides.Length; i++) - { - int stride = strides[i]; - bool isSplit = false; - for (int j = 0; j < splitAxes.Length; j++) - { - if (splitAxes[j] == i) - { - splitStrides[splitStridesOffset + j] = stride; - isSplit = true; - break; - } - } - - if (!isSplit) - { - newStrides[stridesOffset + newStrideIndex++] = stride; - } - } - } - - /// - /// Calculates the 1-d index for n-d indices in layout specified by strides. - /// - /// - /// - /// - /// - public static int GetIndex(int[] strides, ReadOnlySpan indices, int startFromDimension = 0) - { - Debug.Assert(strides.Length == indices.Length); - - int index = 0; - for (int i = startFromDimension; i < indices.Length; i++) - { - index += strides[i] * indices[i]; - } - - return index; - } - - /// - /// Calculates the n-d indices from the 1-d index in a layout specified by strides - /// - /// - /// - /// - /// - /// - public static void GetIndices(ReadOnlySpan strides, bool reverseStride, int index, int[] indices, int startFromDimension = 0) - { - Debug.Assert(reverseStride ? IsAscending(strides) : IsDescending(strides), "Index decomposition requires ordered strides"); - Debug.Assert(strides.Length == indices.Length); - - int remainder = index; - for (int i = startFromDimension; i < strides.Length; i++) - { - // reverse the index for reverseStride so that we divide by largest stride first - var nIndex = reverseStride ? strides.Length - 1 - i : i; - - var stride = strides[nIndex]; - indices[nIndex] = remainder / stride; - remainder %= stride; - } - } - - /// - /// Calculates the n-d indices from the 1-d index in a layout specified by strides - /// - /// - /// - /// - /// - /// - public static void GetIndices(ReadOnlySpan strides, bool reverseStride, int index, Span indices, int startFromDimension = 0) - { - Debug.Assert(reverseStride ? IsAscending(strides) : IsDescending(strides), "Index decomposition requires ordered strides"); - Debug.Assert(strides.Length == indices.Length); - - int remainder = index; - for (int i = startFromDimension; i < strides.Length; i++) - { - // reverse the index for reverseStride so that we divide by largest stride first - var nIndex = reverseStride ? strides.Length - 1 - i : i; - - var stride = strides[nIndex]; - indices[nIndex] = remainder / stride; - remainder %= stride; - } - } - - /// - /// Takes an 1-d index over n-d sourceStrides and recalculates it assuming same n-d coordinates over a different n-d strides - /// - public static int TransformIndexByStrides(int index, int[] sourceStrides, bool sourceReverseStride, int[] transformStrides) - { - Debug.Assert(index >= 0); - Debug.Assert(sourceReverseStride ? IsAscending(sourceStrides) : IsDescending(sourceStrides), "Index decomposition requires ordered strides"); - Debug.Assert(sourceStrides.Length == transformStrides.Length); - - int transformIndex = 0; - int remainder = index; - - for (int i = 0; i < sourceStrides.Length; i++) - { - // reverse the index for reverseStride so that we divide by largest stride first - var nIndex = sourceReverseStride ? sourceStrides.Length - 1 - i : i; - - var sourceStride = sourceStrides[nIndex]; - var transformStride = transformStrides[nIndex]; - - transformIndex += transformStride * (remainder / sourceStride); - remainder %= sourceStride; - } - - return transformIndex; - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/CompressedSparseTensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/CompressedSparseTensor.cs deleted file mode 100644 index b41915acddd5a..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/CompressedSparseTensor.cs +++ /dev/null @@ -1,517 +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.Diagnostics; -using System.Linq; - -namespace System.Numerics.Tensors -{ - /// - /// Represents a tensor using compressed sparse format - /// For a two dimensional tensor this is referred to as compressed sparse row (CSR, CRS, Yale), compressed sparse column (CSC, CCS) - /// - /// In this format, data that is in the same value for the compressed dimension has locality - /// - /// In standard layout of a dense tensor, data with the same value for first dimensions has locality. - /// As such we'll use reverseStride = false (default) to mean that the first dimension is compressed (CSR) - /// and reverseStride = true to mean that the last dimension is compressed (CSC) - /// - /// - /// - public class CompressedSparseTensor : Tensor - { - private Memory values; - private readonly Memory compressedCounts; - private Memory indices; - - private int nonZeroCount; - - private readonly int[] nonCompressedStrides; - private readonly int compressedDimension; - - private const int defaultCapacity = 64; - - /// - /// Constructs a new CompressedSparseTensor of the specified dimensions and stride ordering. - /// - /// An span of integers that represent the size of each dimension of the CompressedSparseTensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - public CompressedSparseTensor(ReadOnlySpan dimensions, bool reverseStride = false) : this(dimensions, defaultCapacity, reverseStride) - { } - - /// - /// Constructs a new CompressedSparseTensor of the specified dimensions, initial capacity, and stride ordering. - /// - /// An span of integers that represent the size of each dimension of the CompressedSparseTensor to create. - /// The number of non-zero values this tensor can store without resizing. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - public CompressedSparseTensor(ReadOnlySpan dimensions, int capacity, bool reverseStride = false) : base(dimensions, reverseStride) - { - nonZeroCount = 0; - compressedDimension = reverseStride ? Rank - 1 : 0; - nonCompressedStrides = (int[])strides.Clone(); - nonCompressedStrides[compressedDimension] = 0; - var compressedDimensionLength = dimensions[compressedDimension]; - compressedCounts = new int[compressedDimensionLength + 1]; - values = new T[capacity]; - indices = new int[capacity]; - } - - /// - /// Constructs a new CompressedSparseTensor of the specified dimensions, wrapping existing backing memory for the contents. - /// Growing this CompressedSparseTensor will re-allocate the backing memory. - /// - /// Memory storing non-zero values to construct this tensor with. - /// Memory storing the counts of non-zero elements at each index of the compressed dimension. - /// Memory storing the linearized index (excluding the compressed dimension) of non-zero elements. - /// The number of valid entries (eg: non-zero values) in and . - /// An span of integers that represent the size of each dimension of the CompressedSparseTensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - public CompressedSparseTensor(Memory values, Memory compressedCounts, Memory indices, int nonZeroCount, ReadOnlySpan dimensions, bool reverseStride = false) : base(dimensions, reverseStride) - { - compressedDimension = reverseStride ? Rank - 1 : 0; - nonCompressedStrides = (int[])strides.Clone(); - nonCompressedStrides[compressedDimension] = 0; - this.values = values; - this.compressedCounts = compressedCounts; - this.indices = indices; - this.nonZeroCount = nonZeroCount; - } - - internal CompressedSparseTensor(Array fromArray, bool reverseStride = false) : base(fromArray, reverseStride) - { - nonZeroCount = 0; - compressedDimension = reverseStride ? Rank - 1 : 0; - nonCompressedStrides = (int[])strides.Clone(); - nonCompressedStrides[compressedDimension] = 0; - var compressedDimensionLength = dimensions[compressedDimension]; - compressedCounts = new int[compressedDimensionLength + 1]; - - int index = 0; - if (reverseStride) - { - // Array is always row-major - var sourceStrides = ArrayUtilities.GetStrides(dimensions); - - foreach (T item in fromArray) - { - if (!item!.Equals(Zero)) - { - var destIndex = ArrayUtilities.TransformIndexByStrides(index, sourceStrides, false, strides); - var compressedIndex = destIndex / strides[compressedDimension]; - var nonCompressedIndex = destIndex % strides[compressedDimension]; - - SetAt(item, compressedIndex, nonCompressedIndex); - } - - index++; - } - } - else - { - foreach (T item in fromArray) - { - if (!item!.Equals(Zero)) - { - var compressedIndex = index / strides[compressedDimension]; - var nonCompressedIndex = index % strides[compressedDimension]; - - SetAt(item, compressedIndex, nonCompressedIndex); - } - - index++; - } - } - } - - /// - /// Obtains the value at the specified indices - /// - /// A span of integers that represent the indices specifying the position of the element to get. - /// The value at the specified position in this Tensor. - public override T this[ReadOnlySpan indices] - { - get - { - var compressedIndex = indices[compressedDimension]; - var nonCompressedIndex = ArrayUtilities.GetIndex(nonCompressedStrides, indices); - - - if (TryFindIndex(compressedIndex, nonCompressedIndex, out int valueIndex)) - { - return values.Span[valueIndex]; - } - - return Zero; - } - - set - { - var compressedIndex = indices[compressedDimension]; - var nonCompressedIndex = ArrayUtilities.GetIndex(nonCompressedStrides, indices); - - SetAt(value, compressedIndex, nonCompressedIndex); - } - } - - /// - /// Gets the value at the specified index, where index is lineraized as a dot product between indices and strides. - /// - /// An integer index computed as a dot-product of indices. - /// The value at the specified position in this Tensor. - public override T GetValue(int index) - { - var compressedDimensionStride = strides[compressedDimension]; - Debug.Assert(compressedDimensionStride == strides.Max()); - - var compressedIndex = index / compressedDimensionStride; - var nonCompressedIndex = index % compressedDimensionStride; - - - if (TryFindIndex(compressedIndex, nonCompressedIndex, out int valueIndex)) - { - return values.Span[valueIndex]; - } - - return Zero; - } - - /// - /// Sets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The new value to set at the specified position in this Tensor. - public override void SetValue(int index, T value) - { - var compressedDimensionStride = strides[compressedDimension]; - Debug.Assert(compressedDimensionStride == strides.Max()); - - var compressedIndex = index / compressedDimensionStride; - var nonCompressedIndex = index % compressedDimensionStride; - - SetAt(value, compressedIndex, nonCompressedIndex); - - } - - /// - /// Gets the number of non-zero values this tensor can store without resizing. - /// - public int Capacity => values.Length; - - /// - /// Get's the number on non-zero values currently being stored in this tensor. - /// - public int NonZeroCount => nonZeroCount; - - /// - /// Memory storing non-zero values. - /// - public Memory Values => values; - - /// - /// Memory storing the counts of non-zero elements at each index of the compressed dimension. - /// - public Memory CompressedCounts => compressedCounts; - - /// - /// Memory storing the linearized index (excluding the compressed dimension) of non-zero elements. - /// - public Memory Indices => indices; - - private void EnsureCapacity(int min, int allocateIndex = -1) - { - if (values.Length < min) - { - var newCapacity = values.Length == 0 ? defaultCapacity : values.Length * 2; - - if (newCapacity > Length) - { - newCapacity = (int)Length; - } - - if (newCapacity < min) - { - newCapacity = min; - } - - Memory newValues = new T[newCapacity]; - Memory newIndices = new int[newCapacity]; - - if (nonZeroCount > 0) - { - if (allocateIndex == -1) - { - var valuesSpan = values.Span.Slice(0, nonZeroCount); - var indicesSpan = indices.Span.Slice(0, nonZeroCount); - - valuesSpan.CopyTo(newValues.Span); - indicesSpan.CopyTo(newIndices.Span); - } - else - { - Debug.Assert(allocateIndex <= nonZeroCount); - // leave a gap at allocateIndex - - // copy range before allocateIndex - if (allocateIndex > 0) - { - var valuesSpan = values.Span.Slice(0, allocateIndex); - var indicesSpan = indices.Span.Slice(0, allocateIndex); - - valuesSpan.CopyTo(newValues.Span); - indicesSpan.CopyTo(newIndices.Span); - } - - if (allocateIndex < nonZeroCount) - { - var valuesSpan = values.Span.Slice(allocateIndex, nonZeroCount - allocateIndex); - var indicesSpan = indices.Span.Slice(allocateIndex, nonZeroCount - allocateIndex); - - var newValuesSpan = newValues.Span.Slice(allocateIndex + 1, nonZeroCount - allocateIndex); - var newIndicesSpan = newIndices.Span.Slice(allocateIndex + 1, nonZeroCount - allocateIndex); - - valuesSpan.CopyTo(newValuesSpan); - indicesSpan.CopyTo(newIndicesSpan); - } - } - } - - values = newValues; - indices = newIndices; - } - } - - private void InsertAt(int valueIndex, T value, int compressedIndex, int nonCompressedIndex) - { - Debug.Assert(valueIndex <= nonZeroCount); - Debug.Assert(compressedIndex < compressedCounts.Length - 1); - - if (values.Length <= valueIndex) - { - // allocate a new array, leaving a gap - EnsureCapacity(valueIndex + 1, valueIndex); - } - else if (nonZeroCount != valueIndex) - { - // shift values to make a gap - values.Span.Slice(valueIndex, nonZeroCount - valueIndex).CopyTo(values.Span.Slice(valueIndex + 1)); - indices.Span.Slice(valueIndex, nonZeroCount - valueIndex).CopyTo(indices.Span.Slice(valueIndex + 1)); - } - - values.Span[valueIndex] = value; - indices.Span[valueIndex] = nonCompressedIndex; - - var compressedCountsSpan = compressedCounts.Span.Slice(compressedIndex + 1); - for (int i = 0; i < compressedCountsSpan.Length; i++) - { - compressedCountsSpan[i]++; - } - nonZeroCount++; - } - - private void RemoveAt(int valueIndex, int compressedIndex) - { - Debug.Assert(valueIndex < nonZeroCount); - Debug.Assert(compressedIndex < compressedCounts.Length - 1); - - // shift values to close the gap - values.Span.Slice(valueIndex + 1, nonZeroCount - valueIndex - 1).CopyTo(values.Span.Slice(valueIndex)); - indices.Span.Slice(valueIndex + 1, nonZeroCount - valueIndex - 1).CopyTo(indices.Span.Slice(valueIndex)); - - var compressedCountsSpan = compressedCounts.Span.Slice(compressedIndex + 1); - for (int i = 0; i < compressedCountsSpan.Length; i++) - { - compressedCountsSpan[i]--; - } - nonZeroCount--; - } - - private void SetAt(T value, int compressedIndex, int nonCompressedIndex) - { - bool isZero = value!.Equals(Zero); - - if (TryFindIndex(compressedIndex, nonCompressedIndex, out int valueIndex)) - { - if (isZero) - { - RemoveAt(valueIndex, compressedIndex); - } - else - { - values.Span[valueIndex] = value; - indices.Span[valueIndex] = nonCompressedIndex; - } - } - else if (!isZero) - { - InsertAt(valueIndex, value, compressedIndex, nonCompressedIndex); - } - } - - /// - /// Trys to find the place to store a value - /// - /// - /// - /// - /// True if element is found at specific index, false if no specific index is found and insertion point is returned - private bool TryFindIndex(int compressedIndex, int nonCompressedIndex, out int valueIndex) - { - if (nonZeroCount == 0) - { - valueIndex = 0; - return false; - } - - Debug.Assert(compressedIndex < compressedCounts.Length - 1); - - var compressedCountsSpan = compressedCounts.Span; - var lowerValueIndex = compressedCountsSpan[compressedIndex]; - var upperValueIndex = compressedCountsSpan[compressedIndex + 1]; - var indicesSpan = indices.Span; - - // could be a faster search - for (valueIndex = lowerValueIndex; valueIndex < upperValueIndex; valueIndex++) - { - if (indicesSpan[valueIndex] == nonCompressedIndex) - { - return true; - } - } - - return false; - } - - /// - /// Creates a shallow copy of this tensor, with new backing storage. - /// - /// A shallow copy of this tensor. - public override Tensor Clone() - { - return new CompressedSparseTensor(values.ToArray(), compressedCounts.ToArray(), indices.ToArray(), nonZeroCount, dimensions, IsReversedStride); - } - - /// - /// Creates a new Tensor of a different type with the specified dimensions and the same layout as this tensor with elements initialized to their default value. - /// - /// Type contained in the returned Tensor. - /// An span of integers that represent the size of each dimension of the CompressedSparseTensor to create. - /// A new tensor with the same layout as this tensor but different type and dimensions. - public override Tensor CloneEmpty(ReadOnlySpan dimensions) - { - return new CompressedSparseTensor(dimensions, IsReversedStride); - } - - /// - /// Reshapes the current tensor to new dimensions. Unlike other Tensor implementations, CompressedSparseTensor<T> must allocate new backing storage to represent a reshaped Tensor. - /// - /// An span of integers that represent the size of each dimension of the CompressedSparseTensor to create. - /// A new tensor that reinterprets the content of this tensor to new dimensions (assuming the same linear index for each element). - public override Tensor Reshape(ReadOnlySpan dimensions) - { - // reshape currently has shallow semantics which are not compatible with the backing storage for CompressedSparseTensor - // which bakes in information about dimensions (compressedCounts and indices) - - var newCompressedDimension = IsReversedStride ? dimensions.Length - 1 : 0; - var newCompressedDimensionLength = dimensions[newCompressedDimension]; - var newCompressedDimensionStride = (int)(Length / newCompressedDimensionLength); - - var newValues = (T[])values.ToArray(); - var newCompressedCounts = new int[newCompressedDimensionLength + 1]; - var newIndices = new int[indices.Length]; - - var compressedIndex = 0; - - var compressedCountsSpan = compressedCounts.Span; - var indicesSpan = indices.Span.Slice(0, nonZeroCount); - for (int valueIndex = 0; valueIndex < indicesSpan.Length; valueIndex++) - { - while (valueIndex >= compressedCountsSpan[compressedIndex + 1]) - { - compressedIndex++; - Debug.Assert(compressedIndex < compressedCounts.Length); - } - - var currentIndex = indicesSpan[valueIndex] + compressedIndex * strides[compressedDimension]; - - newIndices[valueIndex] = currentIndex % newCompressedDimensionStride; - - var newCompressedIndex = currentIndex / newCompressedDimensionStride; - newCompressedCounts[newCompressedIndex + 1] = valueIndex + 1; - } - - return new CompressedSparseTensor(newValues, newCompressedCounts, newIndices, nonZeroCount, dimensions, IsReversedStride); - } - - /// - /// Creates a copy of this tensor as a DenseTensor<T>. - /// - /// A copy of this tensor as a DenseTensor<T> - public override DenseTensor ToDenseTensor() - { - var denseTensor = new DenseTensor(Dimensions, reverseStride: IsReversedStride); - - var compressedIndex = 0; - - var compressedCountsSpan = compressedCounts.Span; - var indicesSpan = indices.Span.Slice(0, nonZeroCount); - var valuesSpan = values.Span.Slice(0, nonZeroCount); - for (int valueIndex = 0; valueIndex < valuesSpan.Length; valueIndex++) - { - while (valueIndex >= compressedCountsSpan[compressedIndex + 1]) - { - compressedIndex++; - Debug.Assert(compressedIndex < compressedCounts.Length); - } - - var index = indicesSpan[valueIndex] + compressedIndex * strides[compressedDimension]; - - denseTensor.SetValue(index, valuesSpan[valueIndex]); - } - - return denseTensor; - } - - /// - /// Creates a copy of this tensor as a new CompressedSparseTensor<T> eliminating any unused space in the backing storage. - /// - /// A copy of this tensor as a CompressedSparseTensor<T>. - public override CompressedSparseTensor ToCompressedSparseTensor() - { - // Create a copy of the backing storage, eliminating any unused space. - var newValues = values.Slice(0, nonZeroCount).ToArray(); - var newIndices = indices.Slice(0, nonZeroCount).ToArray(); - - return new CompressedSparseTensor(newValues, compressedCounts.ToArray(), newIndices, nonZeroCount, dimensions, IsReversedStride); - } - - /// - /// Creates a copy of this tensor as a SparseTensor<T>. - /// - /// A copy of this tensor as a SparseTensor<T>. - public override SparseTensor ToSparseTensor() - { - var sparseTensor = new SparseTensor(dimensions, capacity: NonZeroCount, reverseStride: IsReversedStride); - - var compressedIndex = 0; - - var compressedCountsSpan = compressedCounts.Span; - var indicesSpan = indices.Span.Slice(0, nonZeroCount); - var valuesSpan = values.Span.Slice(0, nonZeroCount); - for (int valueIndex = 0; valueIndex < valuesSpan.Length; valueIndex++) - { - while (valueIndex >= compressedCountsSpan[compressedIndex + 1]) - { - compressedIndex++; - Debug.Assert(compressedIndex < compressedCounts.Length); - } - - var index = indicesSpan[valueIndex] + compressedIndex * strides[compressedDimension]; - - sparseTensor.SetValue(index, valuesSpan[valueIndex]); - } - - return sparseTensor; - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/DenseTensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/DenseTensor.cs deleted file mode 100644 index 5f8715be3d18c..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/DenseTensor.cs +++ /dev/null @@ -1,178 +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.Runtime.InteropServices; - -namespace System.Numerics.Tensors -{ - /// - /// Represents a multi-dimensional collection of objects of type T that can be accessed by indices. DenseTensor stores values in a contiguous sequential block of memory where all values are represented. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - public class DenseTensor : Tensor - { - private readonly Memory memory; - - internal DenseTensor(Array fromArray, bool reverseStride = false) : base(fromArray, reverseStride) - { - // copy initial array - var backingArray = new T[fromArray.Length]; - - int index = 0; - if (reverseStride) - { - // Array is always row-major - var sourceStrides = ArrayUtilities.GetStrides(dimensions); - - foreach (var item in fromArray) - { - var destIndex = ArrayUtilities.TransformIndexByStrides(index++, sourceStrides, false, strides); - backingArray[destIndex] = (T)item!; - } - } - else - { - foreach (var item in fromArray) - { - backingArray[index++] = (T)item!; - } - } - memory = backingArray; - } - - /// - /// Initializes a rank-1 Tensor using the specified . - /// - /// Size of the 1-dimensional tensor - public DenseTensor(int length) : base(length) - { - memory = new T[length]; - } - - /// - /// Initializes a rank-n Tensor using the dimensions specified in . - /// - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - public DenseTensor(ReadOnlySpan dimensions, bool reverseStride = false) : base(dimensions, reverseStride) - { - memory = new T[Length]; - } - - /// - /// Constructs a new DenseTensor of the specified dimensions, wrapping existing backing memory for the contents. - /// - /// - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - public DenseTensor(Memory memory, ReadOnlySpan dimensions, bool reverseStride = false) : base(dimensions, reverseStride) - { - this.memory = memory; - - if (Length != memory.Length) - { - throw new ArgumentException(SR.Format(SR.LengthMustMatch, nameof(memory), memory.Length, nameof(dimensions), Length)); - } - } - - /// - /// Memory storing backing values of this tensor. - /// - public Memory Buffer => memory; - - /// - /// Gets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The value at the specified position in this Tensor. - public override T GetValue(int index) - { - return Buffer.Span[index]; - } - - /// - /// Sets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The new value to set at the specified position in this Tensor. - public override void SetValue(int index, T value) - { - Buffer.Span[index] = value; - } - - protected override void CopyTo(T[] array, int arrayIndex) - { - if (array is null) - { - throw new ArgumentNullException(nameof(array)); - } - - if (array.Length < arrayIndex + Length) - { - throw new ArgumentException(SR.NumberGreaterThenAvailableSpace, nameof(array)); - } - - Buffer.Span.CopyTo(array.AsSpan(arrayIndex)); - } - - protected override int IndexOf(T item) - { - // TODO: use Span.IndexOf when/if it removes the IEquatable type constraint - if (MemoryMarshal.TryGetArray(Buffer, out var arraySegment)) - { - var result = Array.IndexOf(arraySegment.Array!, item, arraySegment.Offset, arraySegment.Count); - if (result != -1) - { - result -= arraySegment.Offset; - } - return result; - } - else - { - return base.IndexOf(item); - } - } - - /// - /// Creates a shallow copy of this tensor, with new backing storage. - /// - /// A shallow copy of this tensor. - public override Tensor Clone() - { - return new DenseTensor(Buffer.ToArray(), dimensions, IsReversedStride); - } - - /// - /// Creates a new Tensor of a different type with the specified dimensions and the same layout as this tensor with elements initialized to their default value. - /// - /// Type contained in the returned Tensor. - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// A new tensor with the same layout as this tensor but different type and dimensions. - public override Tensor CloneEmpty(ReadOnlySpan dimensions) - { - return new DenseTensor(dimensions, IsReversedStride); - } - - /// - /// Reshapes the current tensor to new dimensions, using the same backing storage. - /// - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// A new tensor that reinterprets backing Buffer of this tensor with different dimensions. - public override Tensor Reshape(ReadOnlySpan dimensions) - { - if (dimensions.Length == 0) - { - throw new ArgumentException(SR.DimensionsMustContainElements, nameof(dimensions)); - } - - var newSize = ArrayUtilities.GetProduct(dimensions); - - if (newSize != Length) - { - throw new ArgumentException(SR.Format(SR.CannotReshapeArrayDueToMismatchInLengths, Length, newSize), nameof(dimensions)); - } - - return new DenseTensor(Buffer, dimensions, IsReversedStride); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs deleted file mode 100644 index 83948a0b918b7..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/SparseTensor.cs +++ /dev/null @@ -1,177 +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.Collections.Generic; - -namespace System.Numerics.Tensors -{ - /// - /// Represents a multi-dimensional collection of objects of type T that can be accessed by indices. Unlike other Tensor<T> implementations SparseTensor<T> does not expose its backing storage. It is meant as an intermediate to be used to build other Tensors, such as CompressedSparseTensor. Unlike CompressedSparseTensor where insertions are O(n), insertions to SparseTensor<T> are nominally O(1). - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - public class SparseTensor : Tensor - { - private readonly Dictionary values; - /// - /// Constructs a new SparseTensor of the specified dimensions, initial capacity, and stride ordering. - /// - /// An span of integers that represent the size of each dimension of the SparseTensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - /// The number of non-zero values this tensor can store without resizing. - public SparseTensor(ReadOnlySpan dimensions, bool reverseStride = false, int capacity = 0) : base(dimensions, reverseStride) - { - values = new Dictionary(capacity); - } - - internal SparseTensor(Dictionary values, ReadOnlySpan dimensions, bool reverseStride = false) : base(dimensions, reverseStride) - { - this.values = values; - } - - internal SparseTensor(Array fromArray, bool reverseStride = false) : base(fromArray, reverseStride) - { - values = new Dictionary(fromArray.Length); - - int index = 0; - if (reverseStride) - { - // Array is always row-major - var sourceStrides = ArrayUtilities.GetStrides(dimensions); - - foreach (T item in fromArray) - { - if (!item!.Equals(Zero)) - { - var destIndex = ArrayUtilities.TransformIndexByStrides(index, sourceStrides, false, strides); - values[destIndex] = item; - } - - index++; - } - } - else - { - foreach (T item in fromArray) - { - if (!item!.Equals(Zero)) - { - values[index] = item; - } - - index++; - } - } - } - - /// - /// Gets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The value at the specified position in this Tensor. - public override T GetValue(int index) - { - - if (!values.TryGetValue(index, out T? value)) - { - value = Zero; - } - - return value; - } - - /// - /// Sets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The new value to set at the specified position in this Tensor. - public override void SetValue(int index, T value) - { - if (value!.Equals(Zero)) - { - values.Remove(index); - } - else - { - values[index] = value; - } - } - - /// - /// Get's the number on non-zero values currently being stored in this tensor. - /// - public int NonZeroCount => values.Count; - - /// - /// Creates a shallow copy of this tensor, with new backing storage. - /// - /// A shallow copy of this tensor. - public override Tensor Clone() - { - var valueCopy = new Dictionary(values); - return new SparseTensor(valueCopy, dimensions, IsReversedStride); - } - - /// - /// Creates a new Tensor of a different type with the specified dimensions and the same layout as this tensor with elements initialized to their default value. - /// - /// Type contained in the returned Tensor. - /// An span of integers that represent the size of each dimension of the SparseTensor to create. - /// A new tensor with the same layout as this tensor but different type and dimensions. - public override Tensor CloneEmpty(ReadOnlySpan dimensions) - { - return new SparseTensor(dimensions, IsReversedStride); - } - - /// - /// Reshapes the current tensor to new dimensions, using the same backing storage. - /// - /// An span of integers that represent the size of each dimension of the SparseTensor to create. - /// A new tensor that reinterprets backing storage of this tensor with different dimensions. - public override Tensor Reshape(ReadOnlySpan dimensions) - { - return new SparseTensor(values, dimensions, IsReversedStride); - } - - /// - /// Creates a copy of this tensor as a DenseTensor<T>. - /// - /// A copy of this tensor as a DenseTensor<T> - public override DenseTensor ToDenseTensor() - { - var denseTensor = new DenseTensor(Dimensions, reverseStride: IsReversedStride); - - // only set non-zero values - foreach (var pair in values) - { - denseTensor.SetValue(pair.Key, pair.Value); - } - - return denseTensor; - } - - /// - /// Creates a copy of this tensor as a new SparseTensor<T> eliminating any unused space in the backing storage. - /// - /// A copy of this tensor as a SparseTensor<T> eliminated any usused space in the backing storage. - public override SparseTensor ToSparseTensor() - { - var valueCopy = new Dictionary(values); - return new SparseTensor(valueCopy, dimensions, IsReversedStride); - } - - /// - /// Creates a copy of this tensor as a CompressedSparseTensor<T>. - /// - /// A copy of this tensor as a CompressedSparseTensor<T>. - public override CompressedSparseTensor ToCompressedSparseTensor() - { - var compressedSparseTensor = new CompressedSparseTensor(dimensions, capacity: NonZeroCount, reverseStride: IsReversedStride); - - foreach (var pair in values) - { - compressedSparseTensor.SetValue(pair.Key, pair.Value); - } - return compressedSparseTensor; - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/Tensor.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/Tensor.cs deleted file mode 100644 index f63547682dd24..0000000000000 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/Tensor.cs +++ /dev/null @@ -1,1365 +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.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; - -namespace System.Numerics.Tensors -{ - /// - /// Various methods for creating and manipulating Tensor<T> - /// - public static partial class Tensor - { - /// - /// Creates an identity tensor of the specified size. An identity tensor is a two dimensional tensor with 1s in the diagonal. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - /// Width and height of the identity tensor to create. - /// a by with 1s along the diagonal and zeros elsewhere. - public static Tensor CreateIdentity(int size) - { - return CreateIdentity(size, false, Tensor.One); - } - - /// - /// Creates an identity tensor of the specified size and layout (row vs column major). An identity tensor is a two dimensional tensor with 1s in the diagonal. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - /// Width and height of the identity tensor to create. - /// >False to indicate that the first dimension is most minor (closest) and the last dimension is most major (farthest): row-major. True to indicate that the last dimension is most minor (closest together) and the first dimension is most major (farthest apart): column-major. - /// a by with 1s along the diagonal and zeros elsewhere. - public static Tensor CreateIdentity(int size, bool columMajor) - { - return CreateIdentity(size, columMajor, Tensor.One); - } - - /// - /// Creates an identity tensor of the specified size and layout (row vs column major) using the specified one value. An identity tensor is a two dimensional tensor with 1s in the diagonal. This may be used in case T is a type that doesn't have a known 1 value. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - /// Width and height of the identity tensor to create. - /// >False to indicate that the first dimension is most minor (closest) and the last dimension is most major (farthest): row-major. True to indicate that the last dimension is most minor (closest together) and the first dimension is most major (farthest apart): column-major. - /// Value of that is used along the diagonal. - /// a by with 1s along the diagonal and zeros elsewhere. - public static Tensor CreateIdentity(int size, bool columMajor, T oneValue) - { - Span dimensions = stackalloc int[2]; - dimensions[0] = dimensions[1] = size; - - var result = new DenseTensor(dimensions, columMajor); - - for (int i = 0; i < size; i++) - { - result.SetValue(i * size + i, oneValue); - } - - return result; - } - - /// - /// Creates a n+1-rank tensor using the specified n-rank diagonal. Values not on the diagonal will be filled with zeros. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - /// Tensor representing the diagonal to build the new tensor from. - /// A new tensor of the same layout and order as of one higher rank, with the values of along the diagonal and zeros elsewhere. - public static Tensor CreateFromDiagonal(Tensor diagonal) - { - return CreateFromDiagonal(diagonal, 0); - } - - /// - /// Creates a n+1-dimension tensor using the specified n-dimension diagonal at the specified offset from the center. Values not on the diagonal will be filled with zeros. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - /// Tensor representing the diagonal to build the new tensor from. - /// Offset of diagonal to set in returned tensor. 0 for the main diagonal, less than zero for diagonals below, greater than zero from diagonals above. - /// A new tensor of the same layout and order as of one higher rank, with the values of along the specified diagonal and zeros elsewhere. - public static Tensor CreateFromDiagonal(Tensor diagonal, int offset) - { - if (diagonal.Rank < 1) - { - throw new ArgumentException(SR.Format(SR.MustHaveAtLeastOneDimension, nameof(diagonal)), nameof(diagonal)); - } - - int diagonalLength = diagonal.dimensions[0]; - - // TODO: allow specification of axis1 and axis2? - var rank = diagonal.dimensions.Length + 1; - Span dimensions = rank < ArrayUtilities.StackallocMax ? stackalloc int[rank] : new int[rank]; - - // assume square - var axisLength = diagonalLength + Math.Abs(offset); - dimensions[0] = dimensions[1] = axisLength; - - for (int i = 1; i < diagonal.dimensions.Length; i++) - { - dimensions[i + 1] = diagonal.dimensions[i]; - } - - var result = diagonal.CloneEmpty(dimensions); - - var sizePerDiagonal = diagonal.Length / diagonalLength; - - var diagProjectionStride = diagonal.IsReversedStride && diagonal.Rank > 1 ? diagonal.strides[1] : 1; - var resultProjectionStride = result.IsReversedStride && result.Rank > 2 ? result.strides[2] : 1; - - for (int diagIndex = 0; diagIndex < diagonalLength; diagIndex++) - { - var resultIndex0 = offset < 0 ? diagIndex - offset : diagIndex; - var resultIndex1 = offset > 0 ? diagIndex + offset : diagIndex; - - var resultBase = resultIndex0 * result.strides[0] + resultIndex1 * result.strides[1]; - var diagBase = diagIndex * diagonal.strides[0]; - - for (int diagProjectionOffset = 0; diagProjectionOffset < sizePerDiagonal; diagProjectionOffset++) - { - result.SetValue(resultBase + diagProjectionOffset * resultProjectionStride, - diagonal.GetValue(diagBase + diagProjectionOffset * diagProjectionStride)); - } - } - - return result; - } - } - - /// - /// Represents a multi-dimensional collection of objects of type T that can be accessed by indices. - /// - /// type contained within the Tensor. Typically a value type such as int, double, float, etc. - [DebuggerDisplay("{GetArrayString(false)}")] - // When we cross-compile for frameworks that expose ICloneable this must implement ICloneable as well. - public abstract class Tensor : IList, IList, IReadOnlyList, IStructuralComparable, IStructuralEquatable - { - internal static T Zero - { - get - { - if (typeof(T) == typeof(bool)) - { - return (T)(object)(false); - } - else if (typeof(T) == typeof(byte)) - { - return (T)(object)(byte)(0); - } - else if (typeof(T) == typeof(char)) - { - return (T)(object)(char)(0); - } - else if (typeof(T) == typeof(decimal)) - { - return (T)(object)(decimal)(0); - } - else if (typeof(T) == typeof(double)) - { - return (T)(object)(double)(0); - } - else if (typeof(T) == typeof(float)) - { - return (T)(object)(float)(0); - } - else if (typeof(T) == typeof(int)) - { - return (T)(object)(int)(0); - } - else if (typeof(T) == typeof(long)) - { - return (T)(object)(long)(0); - } - else if (typeof(T) == typeof(sbyte)) - { - return (T)(object)(sbyte)(0); - } - else if (typeof(T) == typeof(short)) - { - return (T)(object)(short)(0); - } - else if (typeof(T) == typeof(uint)) - { - return (T)(object)(uint)(0); - } - else if (typeof(T) == typeof(ulong)) - { - return (T)(object)(ulong)(0); - } - else if (typeof(T) == typeof(ushort)) - { - return (T)(object)(ushort)(0); - } - - throw new NotSupportedException(); - } - } - - internal static T One - { - get - { - if (typeof(T) == typeof(bool)) - { - return (T)(object)(true); - } - else if (typeof(T) == typeof(byte)) - { - return (T)(object)(byte)(1); - } - else if (typeof(T) == typeof(char)) - { - return (T)(object)(char)(1); - } - else if (typeof(T) == typeof(decimal)) - { - return (T)(object)(decimal)(1); - } - else if (typeof(T) == typeof(double)) - { - return (T)(object)(double)(1); - } - else if (typeof(T) == typeof(float)) - { - return (T)(object)(float)(1); - } - else if (typeof(T) == typeof(int)) - { - return (T)(object)(int)(1); - } - else if (typeof(T) == typeof(long)) - { - return (T)(object)(long)(1); - } - else if (typeof(T) == typeof(sbyte)) - { - return (T)(object)(sbyte)(1); - } - else if (typeof(T) == typeof(short)) - { - return (T)(object)(short)(1); - } - else if (typeof(T) == typeof(uint)) - { - return (T)(object)(uint)(1); - } - else if (typeof(T) == typeof(ulong)) - { - return (T)(object)(ulong)(1); - } - else if (typeof(T) == typeof(ushort)) - { - return (T)(object)(ushort)(1); - } - - throw new NotSupportedException(); - } - } - - internal readonly int[] dimensions; - internal readonly int[] strides; - private readonly bool isReversedStride; - - private readonly long length; - - /// - /// Initialize a 1-dimensional tensor of the specified length - /// - /// Size of the 1-dimensional tensor - protected Tensor(int length) - { - dimensions = new[] { length }; - strides = new[] { 1 }; - isReversedStride = false; - this.length = length; - } - - /// - /// Initialize an n-dimensional tensor with the specified dimensions and layout. ReverseStride=true gives a stride of 1-element witdth to the first dimension (0). ReverseStride=false gives a stride of 1-element width to the last dimension (n-1). - /// - /// An span of integers that represent the size of each dimension of the Tensor to create. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - protected Tensor(ReadOnlySpan dimensions, bool reverseStride) - { - if (dimensions.Length == 0) - { - throw new ArgumentException(SR.DimensionsMustContainElements, nameof(dimensions)); - } - - this.dimensions = new int[dimensions.Length]; - long size = 1; - for (int i = 0; i < dimensions.Length; i++) - { - if (dimensions[i] < 1) - { - throw new ArgumentOutOfRangeException(nameof(dimensions), SR.DimensionsMustBePositiveAndNonZero); - } - this.dimensions[i] = dimensions[i]; - size *= dimensions[i]; - } - - strides = ArrayUtilities.GetStrides(dimensions, reverseStride); - isReversedStride = reverseStride; - - length = size; - } - - /// - /// Initializes tensor with same dimensions as array, content of array is ignored. ReverseStride=true gives a stride of 1-element witdth to the first dimension (0). ReverseStride=false gives a stride of 1-element width to the last dimension (n-1). - /// - /// Array from which to derive dimensions. - /// False (default) to indicate that the first dimension is most major (farthest apart) and the last dimension is most minor (closest together): akin to row-major in a rank-2 tensor. True to indicate that the last dimension is most major (farthest apart) and the first dimension is most minor (closest together): akin to column-major in a rank-2 tensor. - protected Tensor(Array fromArray, bool reverseStride) - { - if (fromArray is null) - { - throw new ArgumentNullException(nameof(fromArray)); - } - - if (fromArray.Rank == 0) - { - throw new ArgumentException(SR.ArrayMustContainElements, nameof(fromArray)); - } - - dimensions = new int[fromArray.Rank]; - long size = 1; - for (int i = 0; i < dimensions.Length; i++) - { - dimensions[i] = fromArray.GetLength(i); - size *= dimensions[i]; - } - - strides = ArrayUtilities.GetStrides(dimensions, reverseStride); - isReversedStride = reverseStride; - - length = size; - } - - /// - /// Total length of the Tensor. - /// - public long Length => length; - - /// - /// Rank of the tensor: number of dimensions. - /// - public int Rank => dimensions.Length; - - /// - /// True if strides are reversed (AKA Column-major) - /// - public bool IsReversedStride => isReversedStride; - - /// - /// Returns a readonly view of the dimensions of this tensor. - /// - public ReadOnlySpan Dimensions => dimensions; - - /// - /// Returns a readonly view of the strides of this tensor. - /// - public ReadOnlySpan Strides => strides; - - /// - /// Sets all elements in Tensor to . - /// - /// Value to fill - public virtual void Fill(T value) - { - for (int i = 0; i < Length; i++) - { - SetValue(i, value); - } - } - - /// - /// Creates a shallow copy of this tensor, with new backing storage. - /// - /// A shallow copy of this tensor. - public abstract Tensor Clone(); - - /// - /// Creates a new Tensor with the same layout and dimensions as this tensor with elements initialized to their default value. - /// - /// A new Tensor with the same layout and dimensions as this tensor with elements initialized to their default value. - public virtual Tensor CloneEmpty() - { - return CloneEmpty(dimensions); - } - - /// - /// Creates a new Tensor with the specified dimensions and the same layout as this tensor with elements initialized to their default value. - /// - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// A new Tensor with the same layout as this tensor and specified with elements initialized to their default value. - public virtual Tensor CloneEmpty(ReadOnlySpan dimensions) - { - return CloneEmpty(dimensions); - } - - /// - /// Creates a new Tensor of a different type with the same layout and size as this tensor with elements initialized to their default value. - /// - /// Type contained within the new Tensor. Typically a value type such as int, double, float, etc. - /// A new Tensor with the same layout and dimensions as this tensor with elements of type initialized to their default value. - public virtual Tensor CloneEmpty() - { - return CloneEmpty(dimensions); - } - - /// - /// Creates a new Tensor of a different type with the specified dimensions and the same layout as this tensor with elements initialized to their default value. - /// - /// Type contained within the new Tensor. Typically a value type such as int, double, float, etc. - /// An span of integers that represent the size of each dimension of the DenseTensor to create. - /// A new Tensor with the same layout as this tensor of specified with elements of type initialized to their default value. - public abstract Tensor CloneEmpty(ReadOnlySpan dimensions); - - /// - /// Gets the n-1 dimension diagonal from the n dimension tensor. - /// - /// An n-1 dimension tensor with the values from the main diagonal of this tensor. - public Tensor GetDiagonal() - { - return GetDiagonal(0); - } - - /// - /// Gets the n-1 dimension diagonal from the n dimension tensor at the specified offset from center. - /// - /// Offset of diagonal to set in returned tensor. 0 for the main diagonal, less than zero for diagonals below, greater than zero from diagonals above. - /// An n-1 dimension tensor with the values from the specified diagonal of this tensor. - public Tensor GetDiagonal(int offset) - { - // Get diagonal of first two dimensions for all remaining dimensions - - // diagnonal is as follows: - // { 1, 2, 4 } - // { 8, 3, 9 } - // { 0, 7, 5 } - // The diagonal at offset 0 is { 1, 3, 5 } - // The diagonal at offset 1 is { 2, 9 } - // The diagonal at offset -1 is { 8, 7 } - - if (Rank < 2) - { - throw new InvalidOperationException(SR.Format(SR.CannotComputeDiagonal, nameof(Tensor))); - } - - // TODO: allow specification of axis1 and axis2? - var axisLength0 = dimensions[0]; - var axisLength1 = dimensions[1]; - - // the diagonal will be the length of the smaller axis - // if offset it positive, the length will shift along the second axis - // if the offset is negative, the length will shift along the first axis - // In that way the length of the diagonal will be - // Min(offset < 0 ? axisLength0 + offset : axisLength0, offset > 0 ? axisLength1 - offset : axisLength1) - // To illustrate, consider the following - // { 1, 2, 4, 3, 7 } - // { 8, 3, 9, 2, 6 } - // { 0, 7, 5, 2, 9 } - // The diagonal at offset 0 is { 1, 3, 5 }, Min(3, 5) = 3 - // The diagonal at offset 1 is { 2, 9, 2 }, Min(3, 5 - 1) = 3 - // The diagonal at offset 3 is { 3, 6 }, Min(3, 5 - 3) = 2 - // The diagonal at offset -1 is { 8, 7 }, Min(3 - 1, 5) = 2 - var offsetAxisLength0 = offset < 0 ? axisLength0 + offset : axisLength0; - var offsetAxisLength1 = offset > 0 ? axisLength1 - offset : axisLength1; - - var diagonalLength = Math.Min(offsetAxisLength0, offsetAxisLength1); - - if (diagonalLength <= 0) - { - throw new ArgumentException(SR.Format(SR.CannotComputeDiagonalWithOffset, offset), nameof(offset)); - } - - var newTensorRank = Rank - 1; - var newTensorDimensions = newTensorRank < ArrayUtilities.StackallocMax ? stackalloc int[newTensorRank] : new int[newTensorRank]; - newTensorDimensions[0] = diagonalLength; - - for (int i = 2; i < dimensions.Length; i++) - { - newTensorDimensions[i - 1] = dimensions[i]; - } - - var diagonalTensor = CloneEmpty(newTensorDimensions); - var sizePerDiagonal = diagonalTensor.Length / diagonalTensor.Dimensions[0]; - - var diagProjectionStride = diagonalTensor.IsReversedStride && diagonalTensor.Rank > 1 ? diagonalTensor.strides[1] : 1; - var sourceProjectionStride = IsReversedStride && Rank > 2 ? strides[2] : 1; - - for (int diagIndex = 0; diagIndex < diagonalLength; diagIndex++) - { - var sourceIndex0 = offset < 0 ? diagIndex - offset : diagIndex; - var sourceIndex1 = offset > 0 ? diagIndex + offset : diagIndex; - - var sourceBase = sourceIndex0 * strides[0] + sourceIndex1 * strides[1]; - var diagBase = diagIndex * diagonalTensor.strides[0]; - - for (int diagProjectionIndex = 0; diagProjectionIndex < sizePerDiagonal; diagProjectionIndex++) - { - diagonalTensor.SetValue(diagBase + diagProjectionIndex * diagProjectionStride, - GetValue(sourceBase + diagProjectionIndex * sourceProjectionStride)); - } - } - - return diagonalTensor; - } - - /// - /// Gets a tensor representing the elements below and including the diagonal, with the rest of the elements zero-ed. - /// - /// A tensor with the values from this tensor at and below the main diagonal and zeros elsewhere. - public Tensor GetTriangle() - { - return GetTriangle(0, upper: false); - } - - /// - /// Gets a tensor representing the elements below and including the specified diagonal, with the rest of the elements zero-ed. - /// - /// Offset of diagonal to set in returned tensor. 0 for the main diagonal, less than zero for diagonals below, greater than zero from diagonals above. - /// A tensor with the values from this tensor at and below the specified diagonal and zeros elsewhere. - public Tensor GetTriangle(int offset) - { - return GetTriangle(offset, upper: false); - } - - /// - /// Gets a tensor representing the elements above and including the diagonal, with the rest of the elements zero-ed. - /// - /// A tensor with the values from this tensor at and above the main diagonal and zeros elsewhere. - public Tensor GetUpperTriangle() - { - return GetTriangle(0, upper: true); - } - - /// - /// Gets a tensor representing the elements above and including the specified diagonal, with the rest of the elements zero-ed. - /// - /// Offset of diagonal to set in returned tensor. 0 for the main diagonal, less than zero for diagonals below, greater than zero from diagonals above. - /// A tensor with the values from this tensor at and above the specified diagonal and zeros elsewhere. - public Tensor GetUpperTriangle(int offset) - { - return GetTriangle(offset, upper: true); - } - - private Tensor GetTriangle(int offset, bool upper) - { - if (Rank < 2) - { - throw new InvalidOperationException(SR.Format(SR.CannotComputeTriangle, nameof(Tensor))); - } - - // Similar to get diagonal except it gets every element below and including the diagonal. - - // TODO: allow specification of axis1 and axis2? - var axisLength0 = dimensions[0]; - var axisLength1 = dimensions[1]; - var diagonalLength = Math.Max(axisLength0, axisLength1); - - var result = CloneEmpty(); - - var projectionSize = Length / (axisLength0 * axisLength1); - var projectionStride = IsReversedStride && Rank > 2 ? strides[2] : 1; - - for (int diagIndex = 0; diagIndex < diagonalLength; diagIndex++) - { - // starting point for the tri - var triIndex0 = offset > 0 ? diagIndex - offset : diagIndex; - var triIndex1 = offset > 0 ? diagIndex : diagIndex + offset; - - // for lower triangle, iterate index0 keeping same index1 - // for upper triangle, iterate index1 keeping same index0 - - if (triIndex0 < 0) - { - if (upper) - { - // out of bounds, ignore this diagIndex. - continue; - } - else - { - // set index to 0 so that we can iterate on the remaining index0 values. - triIndex0 = 0; - } - } - - if (triIndex1 < 0) - { - if (upper) - { - // set index to 0 so that we can iterate on the remaining index1 values. - triIndex1 = 0; - } - else - { - // out of bounds, ignore this diagIndex. - continue; - } - } - - while ((triIndex1 < axisLength1) && (triIndex0 < axisLength0)) - { - var baseIndex = triIndex0 * strides[0] + triIndex1 * result.strides[1]; - - for (int projectionIndex = 0; projectionIndex < projectionSize; projectionIndex++) - { - var index = baseIndex + projectionIndex * projectionStride; - - result.SetValue(index, GetValue(index)); - } - - if (upper) - { - triIndex1++; - } - else - { - triIndex0++; - } - } - } - - return result; - } - - /// - /// Reshapes the current tensor to new dimensions, using the same backing storage if possible. - /// - /// An span of integers that represent the size of each dimension of the Tensor to create. - /// A new tensor that reinterprets this tensor with different dimensions. - public abstract Tensor Reshape(ReadOnlySpan dimensions); - - /// - /// Obtains the value at the specified indices - /// - /// A one-dimensional array of integers that represent the indices specifying the position of the element to get. - /// The value at the specified position in this Tensor. - public virtual T this[params int[] indices] - { - get - { - if (indices is null) - { - throw new ArgumentNullException(nameof(indices)); - } - - var span = new ReadOnlySpan(indices); - return this[span]; - } - - set - { - if (indices is null) - { - throw new ArgumentNullException(nameof(indices)); - } - - var span = new ReadOnlySpan(indices); - this[span] = value; - } - } - - /// - /// Obtains the value at the specified indices - /// - /// A span integers that represent the indices specifying the position of the element to get. - /// The value at the specified position in this Tensor. - public virtual T this[ReadOnlySpan indices] - { - get - { - return GetValue(ArrayUtilities.GetIndex(strides, indices)); - } - - set - { - SetValue(ArrayUtilities.GetIndex(strides, indices), value); - } - } - - /// - /// Gets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The value at the specified position in this Tensor. - public abstract T GetValue(int index); - - /// - /// Sets the value at the specified index, where index is a linearized version of n-dimension indices using strides. - /// - /// An integer index computed as a dot-product of indices. - /// The new value to set at the specified position in this Tensor. - public abstract void SetValue(int index, T value); - - /// - /// The type that implements enumerators for instances. - /// - public struct Enumerator : IEnumerator - { - private readonly Tensor _tensor; - private int _index; - - internal Enumerator(Tensor tensor) - { - Debug.Assert(tensor != null); - - _tensor = tensor; - _index = 0; - Current = default!; - } - - public T Current { get; private set; } - - object? IEnumerator.Current => Current; - - public bool MoveNext() - { - if (_index < _tensor.Length) - { - Current = _tensor.GetValue(_index); - ++_index; - return true; - } - else - { - Current = default!; - return false; - } - } - - /// - /// Resets the enumerator to the beginning. - /// - public void Reset() - { - _index = 0; - Current = default!; - } - - /// - /// Disposes the enumerator. - /// - public void Dispose() { } - } - - /// - /// Gets an enumerator that enumerates the elements of the . - /// - /// An enumerator for the current . - public Enumerator GetEnumerator() => new Enumerator(this); - - #region statics - /// - /// Performs a value comparison of the content and shape of two tensors. Two tensors are equal if they have the same shape and same value at every set of indices. If not equal a tensor is greater or less than another tensor based on the first non-equal element when enumerating in linear order. - /// - /// - /// - /// - public static int Compare(Tensor left, Tensor right) - { - return StructuralComparisons.StructuralComparer.Compare(left, right); - } - - /// - /// Performs a value equality comparison of the content of two tensors. Two tensors are equal if they have the same shape and same value at every set of indices. - /// - /// - /// - /// - public static bool Equals(Tensor left, Tensor right) - { - return StructuralComparisons.StructuralEqualityComparer.Equals(left, right); - } - #endregion - - #region IEnumerable members - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - #endregion - - #region ICollection members - int ICollection.Count => (int)Length; - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot => this; // backingArray.this? - - void ICollection.CopyTo(Array array, int index) - { - if (array is T[] destinationArray) - { - CopyTo(destinationArray, index); - } - else - { - if (array == null) - { - throw new ArgumentNullException(nameof(array)); - } - if (array.Rank != 1) - { - throw new ArgumentException(SR.OnlySingleDimensionalArraysSupported, nameof(array)); - } - if (array.Length < index + Length) - { - throw new ArgumentException(SR.NumberGreaterThenAvailableSpace, nameof(array)); - } - - for (int i = 0; i < length; i++) - { - array.SetValue(GetValue(i), index + i); - } - } - } - #endregion - - #region IList members - object? IList.this[int index] - { - get - { - return GetValue(index); - } - set - { - try - { - SetValue(index, (T)value!); - } - catch (InvalidCastException) - { - throw new ArgumentException(SR.Format(SR.ValueIsNotOfType, value, typeof(T))); - } - } - } - - public bool IsFixedSize => true; - - public bool IsReadOnly => false; - - int IList.Add(object? value) - { - throw new InvalidOperationException(); - } - - void IList.Clear() - { - Fill(default!); - } - - bool IList.Contains(object? value) - { - if (IsCompatibleObject(value!)) - { - return Contains((T)value!); - } - return false; - } - - int IList.IndexOf(object? value) - { - if (IsCompatibleObject(value!)) - { - return IndexOf((T)value!); - } - return -1; - } - - void IList.Insert(int index, object? value) - { - throw new InvalidOperationException(); - } - - void IList.Remove(object? value) - { - throw new InvalidOperationException(); - } - - void IList.RemoveAt(int index) - { - throw new InvalidOperationException(); - } - #endregion - - #region IEnumerable members - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - #endregion - - #region ICollection members - int ICollection.Count => (int)Length; - - void ICollection.Add(T item) - { - throw new InvalidOperationException(); - } - - void ICollection.Clear() - { - Fill(default!); - } - - bool ICollection.Contains(T item) - { - return Contains(item); - } - - /// - /// Determines whether an element is in the Tensor<T>. - /// - /// - /// The object to locate in the Tensor<T>. The value can be null for reference types. - /// - /// - /// true if item is found in the Tensor<T>; otherwise, false. - /// - protected virtual bool Contains(T item) - { - return Length != 0 && IndexOf(item) != -1; - } - - void ICollection.CopyTo(T[] array, int arrayIndex) - { - CopyTo(array, arrayIndex); - } - - /// - /// Copies the elements of the Tensor<T> to an Array, starting at a particular Array index. - /// - /// - /// The one-dimensional Array that is the destination of the elements copied from Tensor<T>. The Array must have zero-based indexing. - /// - /// - /// The zero-based index in array at which copying begins. - /// - protected virtual void CopyTo(T[] array, int arrayIndex) - { - if (array is null) - { - throw new ArgumentNullException(nameof(array)); - } - - if (array.Length < arrayIndex + Length) - { - throw new ArgumentException(SR.NumberGreaterThenAvailableSpace, nameof(array)); - } - - for (int i = 0; i < length; i++) - { - array[arrayIndex + i] = GetValue(i); - } - } - - bool ICollection.Remove(T item) - { - throw new InvalidOperationException(); - } - #endregion - - #region IReadOnlyCollection members - - int IReadOnlyCollection.Count => (int)Length; - - #endregion - - #region IList members - T IList.this[int index] - { - get { return GetValue(index); } - set { SetValue(index, value); } - } - - int IList.IndexOf(T item) - { - return IndexOf(item); - } - - /// - /// Determines the index of a specific item in the Tensor<T>. - /// - /// The object to locate in the Tensor<T>. - /// The index of item if found in the tensor; otherwise, -1. - protected virtual int IndexOf(T item) - { - for (int i = 0; i < Length; i++) - { - if (GetValue(i)!.Equals(item)) - { - return i; - } - } - - return -1; - } - - void IList.Insert(int index, T item) - { - throw new InvalidOperationException(); - } - - void IList.RemoveAt(int index) - { - throw new InvalidOperationException(); - } - #endregion - - #region IReadOnlyList members - - T IReadOnlyList.this[int index] => GetValue(index); - - #endregion - - #region IStructuralComparable members - int IStructuralComparable.CompareTo(object? other, IComparer comparer) - { - if (other == null) - { - return 1; - } - - if (other is Tensor) - { - return CompareTo((Tensor)other, comparer); - } - - var otherArray = other as Array; - - if (otherArray != null) - { - return CompareTo(otherArray, comparer); - } - - throw new ArgumentException(SR.Format(SR.CannotCompare, nameof(Tensor), other.GetType()), nameof(other)); - } - - private int CompareTo(Tensor other, IComparer comparer) - { - if (Rank != other.Rank) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithRank, nameof(Tensor), Rank, nameof(other), other.Rank), nameof(other)); - } - - for (int i = 0; i < dimensions.Length; i++) - { - if (dimensions[i] != other.dimensions[i]) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithDifferentDimension, nameof(Tensor), i, dimensions[i], other.dimensions[i]), nameof(other)); - } - } - - int result = 0; - - if (IsReversedStride == other.IsReversedStride) - { - for (int i = 0; i < Length; i++) - { - result = comparer.Compare(GetValue(i), other.GetValue(i)); - if (result != 0) - { - break; - } - } - } - else - { - var indices = Rank < ArrayUtilities.StackallocMax ? stackalloc int[Rank] : new int[Rank]; - for (int i = 0; i < Length; i++) - { - ArrayUtilities.GetIndices(strides, IsReversedStride, i, indices); - result = comparer.Compare(this[indices], other[indices]); - if (result != 0) - { - break; - } - } - } - - return result; - } - - private int CompareTo(Array other, IComparer comparer) - { - if (Rank != other.Rank) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithRank, nameof(Tensor), Rank, nameof(Array), other.Rank), nameof(other)); - } - - for (int i = 0; i < dimensions.Length; i++) - { - var otherDimension = other.GetLength(i); - if (dimensions[i] != otherDimension) - { - throw new ArgumentException(SR.Format(SR.CannotCompareToWithDifferentDimension, nameof(Tensor), nameof(Array), i, dimensions[i], otherDimension), nameof(other)); - } - } - - int result = 0; - var indices = new int[Rank]; - for (int i = 0; i < Length; i++) - { - ArrayUtilities.GetIndices(strides, IsReversedStride, i, indices); - - result = comparer.Compare(GetValue(i), other.GetValue(indices)); - - if (result != 0) - { - break; - } - } - - return result; - } - #endregion - - #region IStructuralEquatable members - bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) - { - if (other == null) - { - return false; - } - - if (other is Tensor) - { - return Equals((Tensor)other, comparer); - } - - var otherArray = other as Array; - - if (otherArray != null) - { - return Equals(otherArray, comparer); - } - - throw new ArgumentException(SR.Format(SR.CannotCompare, nameof(Tensor), other.GetType()), nameof(other)); - } - - private bool Equals(Tensor other, IEqualityComparer comparer) - { - if (Rank != other.Rank) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithRank, nameof(Tensor), Rank, nameof(other), other.Rank), nameof(other)); - } - - for (int i = 0; i < dimensions.Length; i++) - { - if (dimensions[i] != other.dimensions[i]) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithDifferentDimension, nameof(Tensor), i, dimensions[i], other.dimensions[i]), nameof(other)); - } - } - - if (IsReversedStride == other.IsReversedStride) - { - for (int i = 0; i < Length; i++) - { - if (!comparer.Equals(GetValue(i), other.GetValue(i))) - { - return false; - } - } - } - else - { - var indices = Rank < ArrayUtilities.StackallocMax ? stackalloc int[Rank] : new int[Rank]; - for (int i = 0; i < Length; i++) - { - ArrayUtilities.GetIndices(strides, IsReversedStride, i, indices); - - if (!comparer.Equals(this[indices], other[indices])) - { - return false; - } - } - } - - return true; - } - - private bool Equals(Array other, IEqualityComparer comparer) - { - if (Rank != other.Rank) - { - throw new ArgumentException(SR.Format(SR.CannotCompareWithRank, nameof(Tensor), Rank, nameof(Array), other.Rank), nameof(other)); - } - - for (int i = 0; i < dimensions.Length; i++) - { - var otherDimension = other.GetLength(i); - if (dimensions[i] != otherDimension) - { - throw new ArgumentException(SR.Format(SR.CannotCompareToWithDifferentDimension, nameof(Tensor), nameof(Array), i, dimensions[i], otherDimension), nameof(other)); - } - } - - var indices = new int[Rank]; - for (int i = 0; i < Length; i++) - { - ArrayUtilities.GetIndices(strides, IsReversedStride, i, indices); - - if (!comparer.Equals(GetValue(i), other.GetValue(indices))) - { - return false; - } - } - - return true; - } - int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) - { - int hashCode = 0; - // this ignores shape, which is fine it just means we'll have hash collisions for things - // with the same content and different shape. - for (int i = 0; i < Length; i++) - { - hashCode ^= comparer.GetHashCode(GetValue(i)!); - } - - return hashCode; - } - #endregion - - #region Translations - - /// - /// Creates a copy of this tensor as a DenseTensor<T>. If this tensor is already a DenseTensor<T> calling this method is equivalent to calling Clone(). - /// - /// - public virtual DenseTensor ToDenseTensor() - { - var denseTensor = new DenseTensor(Dimensions, IsReversedStride); - for (int i = 0; i < Length; i++) - { - denseTensor.SetValue(i, GetValue(i)); - } - return denseTensor; - } - - - /// - /// Creates a copy of this tensor as a SparseTensor<T>. If this tensor is already a SparseTensor<T> calling this method is equivalent to calling Clone(). - /// - /// - public virtual SparseTensor ToSparseTensor() - { - var sparseTensor = new SparseTensor(Dimensions, IsReversedStride); - for (int i = 0; i < Length; i++) - { - sparseTensor.SetValue(i, GetValue(i)); - } - return sparseTensor; - } - - /// - /// Creates a copy of this tensor as a CompressedSparseTensor<T>. If this tensor is already a CompressedSparseTensor<T> calling this method is equivalent to calling Clone(). - /// - /// - public virtual CompressedSparseTensor ToCompressedSparseTensor() - { - var compressedSparseTensor = new CompressedSparseTensor(Dimensions, IsReversedStride); - for (int i = 0; i < Length; i++) - { - compressedSparseTensor.SetValue(i, GetValue(i)); - } - return compressedSparseTensor; - } - - #endregion - - public string GetArrayString(bool includeWhitespace = true) - { - var builder = new StringBuilder(); - - var strides = ArrayUtilities.GetStrides(dimensions); - var indices = new int[Rank]; - var innerDimension = Rank - 1; - var innerLength = dimensions[innerDimension]; - - int indent = 0; - for (int outerIndex = 0; outerIndex < Length; outerIndex += innerLength) - { - ArrayUtilities.GetIndices(strides, false, outerIndex, indices); - - while ((indent < innerDimension) && (indices[indent] == 0)) - { - // start up - if (includeWhitespace) - { - Indent(builder, indent); - } - indent++; - builder.Append('{'); - if (includeWhitespace) - { - builder.AppendLine(); - } - } - - for (int innerIndex = 0; innerIndex < innerLength; innerIndex++) - { - indices[innerDimension] = innerIndex; - - if ((innerIndex == 0)) - { - if (includeWhitespace) - { - Indent(builder, indent); - } - builder.Append('{'); - } - else - { - builder.Append(','); - } - builder.Append(this[indices]); - } - builder.Append('}'); - - for (int i = Rank - 2; i >= 0; i--) - { - var lastIndex = dimensions[i] - 1; - if (indices[i] == lastIndex) - { - // close out - --indent; - if (includeWhitespace) - { - builder.AppendLine(); - Indent(builder, indent); - } - builder.Append('}'); - } - else - { - builder.Append(','); - if (includeWhitespace) - { - builder.AppendLine(); - } - break; - } - } - } - - return builder.ToString(); - } - - private static void Indent(StringBuilder builder, int tabs, int spacesPerTab = 4) - { - for (int tab = 0; tab < tabs; tab++) - { - for (int space = 0; space < spacesPerTab; space++) - { - builder.Append(' '); - } - } - } - - private static bool IsCompatibleObject(object value) - { - // Non-null values are fine. Only accept nulls if T is a class or Nullable. - // Note that default(T) is not equal to null for value types except when T is Nullable. - return ((value is T) || (value == null && default(T) == null)); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs new file mode 100644 index 0000000000000..10f29183ea286 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.cs @@ -0,0 +1,467 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Numerics.Tensors +{ + /// Performs primitive tensor operations over spans of memory. + public static class TensorPrimitives + { + /// Computes the element-wise result of: + . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = [i] + [i]. + public static void Add(ReadOnlySpan x, ReadOnlySpan y, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] + y[i]; + } + } + + /// Computes the element-wise result of: + . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = [i] + . + public static void Add(ReadOnlySpan x, float y, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] + y; + } + } + + /// Computes the element-wise result of: - . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = [i] - [i]. + public static void Subtract(ReadOnlySpan x, ReadOnlySpan y, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] - y[i]; + } + } + + /// Computes the element-wise result of: - . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = [i] - . + public static void Subtract(ReadOnlySpan x, float y, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] - y; + } + } + + /// Computes the element-wise result of: * . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = [i] * . + public static void Multiply(ReadOnlySpan x, ReadOnlySpan y, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] * y[i]; + } + } + + /// Computes the element-wise result of: * . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// + /// This method effectively does [i] = [i] * . + /// This method corresponds to the scal method defined by BLAS1. + /// + public static void Multiply(ReadOnlySpan x, float y, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] * y; + } + } + + /// Computes the element-wise result of: / . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = [i] / . + public static void Divide(ReadOnlySpan x, ReadOnlySpan y, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] / y[i]; + } + } + + /// Computes the element-wise result of: / . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = [i] / . + public static void Divide(ReadOnlySpan x, float y, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = x[i] / y; + } + } + + /// Computes the element-wise result of: -. + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = -[i]. + public static void Negate(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = -x[i]; + } + } + + /// Computes the element-wise result of: ( + ) * . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The third tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = ([i] + [i]) * [i]. + public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan multiplier, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length != multiplier.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(multiplier)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] + y[i]) * multiplier[i]; + } + } + + /// Computes the element-wise result of: ( + ) * . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The third tensor, represented as a scalar. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = ([i] + [i]) * . + public static void AddMultiply(ReadOnlySpan x, ReadOnlySpan y, float multiplier, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] + y[i]) * multiplier; + } + } + + /// Computes the element-wise result of: ( + ) * . + /// The first tensor, represented as a span. + /// The second tensor, represented as a scalar. + /// The third tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = ([i] + ) * [i]. + public static void AddMultiply(ReadOnlySpan x, float y, ReadOnlySpan multiplier, Span destination) + { + if (x.Length != multiplier.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(multiplier)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] + y) * multiplier[i]; + } + } + + /// Computes the element-wise result of: ( * ) + . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The third tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = ([i] * [i]) + [i]. + public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, ReadOnlySpan addend, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length != addend.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(addend)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] * y[i]) + addend[i]; + } + } + + /// Computes the element-wise result of: ( * ) + . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The third tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// + /// This method effectively does [i] = ([i] * [i]) + . + /// This method corresponds to the axpy method defined by BLAS1. + /// + public static void MultiplyAdd(ReadOnlySpan x, ReadOnlySpan y, float addend, Span destination) + { + if (x.Length != y.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(y)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] * y[i]) + addend; + } + } + + /// Computes the element-wise result of: ( * ) + . + /// The first tensor, represented as a span. + /// The second tensor, represented as a span. + /// The third tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Length of '' must be same as length of ''. + /// Destination is too short. + /// This method effectively does [i] = ([i] * ) + [i]. + public static void MultiplyAdd(ReadOnlySpan x, float y, ReadOnlySpan addend, Span destination) + { + if (x.Length != addend.Length) + { + ThrowHelper.ThrowArgument_SpansMustHaveSameLength(nameof(x), nameof(addend)); + } + + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = (x[i] * y) + addend[i]; + } + } + + /// Computes the element-wise result of: pow(e, ). + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = .Exp([i]). + public static void Exp(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = MathF.Exp(x[i]); + } + } + + /// Computes the element-wise result of: ln(). + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = .Log([i]). + public static void Log(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = MathF.Log(x[i]); + } + } + + /// Computes the element-wise result of: cosh(). + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = .Cosh([i]). + public static void Cosh(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = MathF.Cosh(x[i]); + } + } + + /// Computes the element-wise result of: sinh(). + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = .Sinh([i]). + public static void Sinh(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = MathF.Sinh(x[i]); + } + } + + /// Computes the element-wise result of: tanh(). + /// The tensor, represented as a span. + /// The destination tensor, represented as a span. + /// Destination is too short. + /// This method effectively does [i] = .Tanh([i]). + public static void Tanh(ReadOnlySpan x, Span destination) + { + if (x.Length > destination.Length) + { + ThrowHelper.ThrowArgument_DestinationTooShort(); + } + + for (int i = 0; i < x.Length; i++) + { + destination[i] = MathF.Tanh(x[i]); + } + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs new file mode 100644 index 0000000000000..5ae36ffbed768 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/src/System/ThrowHelper.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; + +namespace System +{ + // + // This pattern of easily inlinable "void Throw" routines that stack on top of NoInlining factory methods + // is a compromise between older JITs and newer JITs (RyuJIT in .NET Core 1.1.0+ and .NET Framework in 4.6.3+). + // This package is explicitly targeted at older JITs as newer runtimes expect to implement Span intrinsically for + // best performance. + // + // The aim of this pattern is three-fold + // 1. Extracting the throw makes the method preforming the throw in a conditional branch smaller and more inlinable + // 2. Extracting the throw from generic method to non-generic method reduces the repeated codegen size for value types + // 3a. Newer JITs will not inline the methods that only throw and also recognise them, move the call to cold section + // and not add stack prep and unwind before calling https://github.com/dotnet/coreclr/pull/6103 + // 3b. Older JITs will inline the throw itself and move to cold section; but not inline the non-inlinable exception + // factory methods - still maintaining advantages 1 & 2 + // + + internal static class ThrowHelper + { + [DoesNotReturn] + public static void ThrowArgument_DestinationTooShort() => throw new ArgumentException(SR.Argument_DestinationTooShort); + + [DoesNotReturn] + public static void ThrowArgument_SpansMustHaveSameLength(string paramName1, string paramName2) + => throw new ArgumentException(SR.Format(SR.Argument_SpansMustHaveSameLength, paramName1, paramName2), paramName1); + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/NativeMemory.cs b/src/libraries/System.Numerics.Tensors/tests/NativeMemory.cs deleted file mode 100644 index b5c9ef8c2c2c9..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/NativeMemory.cs +++ /dev/null @@ -1,108 +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.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace System.Numerics.Tensors.Tests -{ - public class NativeMemory : MemoryManager - { - private bool disposed = false; - private int refCount = 0; - private IntPtr memory; - private int length; - - public NativeMemory(IntPtr memory, int length) - { - this.memory = memory; - this.length = length; - } - - public unsafe NativeMemory(void* memory, int length) - { - this.memory = (IntPtr)memory; - this.length = length; - } - - ~NativeMemory() - { - Dispose(false); - } - - public static NativeMemory Allocate(int length) - { - // typically this would call into a native method appropriate for the platform - // or the constructors above would be used to wrap the native pointer - IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf() * length); - return new NativeMemory(memory, length); - } - - public bool IsDisposed => disposed; - - public unsafe override Span GetSpan() => new Span((void*)memory, length); - - protected bool IsRetained => refCount > 0; - - public override MemoryHandle Pin(int elementIndex = 0) - { - unsafe - { - Retain(); - if ((uint)elementIndex > length) throw new ArgumentOutOfRangeException(nameof(elementIndex)); - void* pointer = Unsafe.Add((void*)memory, elementIndex); - return new MemoryHandle(pointer, default, this); - } - } - - public bool Release() - { - int newRefCount = Interlocked.Decrement(ref refCount); - - if (newRefCount < 0) - { - throw new InvalidOperationException("Unmatched Release/Retain"); - } - - return newRefCount != 0; - } - - public void Retain() - { - if (disposed) - { - throw new ObjectDisposedException(nameof(NativeMemory)); - } - - Interlocked.Increment(ref refCount); - } - - protected override void Dispose(bool disposing) - { - if (disposed) - { - return; - } - - // typically this would call into a native method appropriate for the platform - Marshal.FreeHGlobal(memory); - memory = IntPtr.Zero; - - disposed = true; - } - - protected override bool TryGetArray(out ArraySegment arraySegment) - { - // cannot expose managed array - arraySegment = default; - return false; - } - - public override void Unpin() - { - Release(); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj index 042e4791b6a3d..d78f1cd7e9e03 100644 --- a/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj +++ b/src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csproj @@ -1,41 +1,17 @@ + - true $(NetCoreAppCurrent);$(NetFrameworkMinimum) + true + - - - True - True - TensorArithmetic.tt - - - - True - True - TensorOperations.tt - - - - - - - TextTemplatingFileGenerator - TensorArithmetic.cs - - - TextTemplatingFileGenerator - TensorOperations.cs - - + + - - - - + \ No newline at end of file diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.cs b/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.cs deleted file mode 100644 index 6dae2ec685425..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.cs +++ /dev/null @@ -1,16165 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - internal interface ITensorArithmetic - { - T One { get; } - T Zero { get; } - void Add(Tensor left, Tensor right, Tensor result); - void Add(Tensor tensor, T scalar, Tensor result); - void And(Tensor left, Tensor right, Tensor result); - void And(Tensor tensor, T scalar, Tensor result); - void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result); - void Decrement(Tensor tensor, Tensor result); - void Divide(Tensor left, Tensor right, Tensor result); - void Divide(Tensor tensor, T scalar, Tensor result); - void Equals(Tensor left, Tensor right, Tensor result); - void GreaterThan(Tensor left, Tensor right, Tensor result); - void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result); - void Increment(Tensor tensor, Tensor result); - void LeftShift(Tensor tensor, int value, Tensor result); - void LessThan(Tensor left, Tensor right, Tensor result); - void LessThanOrEqual(Tensor left, Tensor right, Tensor result); - void Modulo(Tensor left, Tensor right, Tensor result); - void Modulo(Tensor tensor, T scalar, Tensor result); - void Multiply(Tensor left, Tensor right, Tensor result); - void Multiply(Tensor tensor, T scalar, Tensor result); - void NotEquals(Tensor left, Tensor right, Tensor result); - void Or(Tensor left, Tensor right, Tensor result); - void Or(Tensor tensor, T scalar, Tensor result); - void RightShift(Tensor tensor, int value, Tensor result); - void Subtract(Tensor left, Tensor right, Tensor result); - void Subtract(Tensor tensor, T scalar, Tensor result); - void UnaryMinus(Tensor tensor, Tensor result); - void UnaryPlus(Tensor tensor, Tensor result); - void Xor(Tensor left, Tensor right, Tensor result); - void Xor(Tensor tensor, T scalar, Tensor result); - } - - internal static class TensorArithmetic - { - public static ITensorArithmetic Instance => TensorArithmetic.GetArithmetic(); - } - - internal static class TensorArithmetic - { - public static ITensorArithmetic GetArithmetic() - { - if (typeof(T) == typeof(bool)) - { - return (ITensorArithmetic)new BoolArithmetic(); - } - else if (typeof(T) == typeof(byte)) - { - return (ITensorArithmetic)new ByteArithmetic(); - } - else if (typeof(T) == typeof(char)) - { - return (ITensorArithmetic)new CharArithmetic(); - } - else if (typeof(T) == typeof(decimal)) - { - return (ITensorArithmetic)new DecimalArithmetic(); - } - else if (typeof(T) == typeof(double)) - { - return (ITensorArithmetic)new DoubleArithmetic(); - } - else if (typeof(T) == typeof(float)) - { - return (ITensorArithmetic)new FloatArithmetic(); - } - else if (typeof(T) == typeof(int)) - { - return (ITensorArithmetic)new IntArithmetic(); - } - else if (typeof(T) == typeof(long)) - { - return (ITensorArithmetic)new LongArithmetic(); - } - else if (typeof(T) == typeof(sbyte)) - { - return (ITensorArithmetic)new SByteArithmetic(); - } - else if (typeof(T) == typeof(short)) - { - return (ITensorArithmetic)new ShortArithmetic(); - } - else if (typeof(T) == typeof(uint)) - { - return (ITensorArithmetic)new UIntArithmetic(); - } - else if (typeof(T) == typeof(ulong)) - { - return (ITensorArithmetic)new ULongArithmetic(); - } - else if (typeof(T) == typeof(ushort)) - { - return (ITensorArithmetic)new UShortArithmetic(); - } - return null; - } - } - - internal class BoolArithmetic : ITensorArithmetic - { - public bool One => true; - public bool Zero => false; - - public void Add(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Add(Tensor tensor, bool scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, bool scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - throw new NotSupportedException(); - } - public void Decrement(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Divide(Tensor tensor, bool scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Increment(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Modulo(Tensor tensor, bool scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Multiply(Tensor tensor, bool scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, bool scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Subtract(Tensor tensor, bool scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, bool scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (bool)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Add(DenseTensor tensor, bool scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, bool scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Divide(DenseTensor tensor, bool scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Modulo(DenseTensor tensor, bool scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Multiply(DenseTensor tensor, bool scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, bool scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Subtract(DenseTensor tensor, bool scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, bool scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (bool)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (bool)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class ByteArithmetic : ITensorArithmetic - { - public byte One => 1; - public byte Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - byte sum = (byte)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (byte)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, byte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (byte)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - byte sum = (byte)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (byte)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, byte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (byte)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (byte)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class CharArithmetic : ITensorArithmetic - { - public char One => (char)1; - public char Zero => (char)0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - char sum = (char)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (char)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, char scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (char)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - char sum = (char)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (char)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, char scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (char)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (char)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class DecimalArithmetic : ITensorArithmetic - { - public decimal One => 1; - public decimal Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, decimal scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void And(Tensor tensor, decimal scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - decimal sum = (decimal)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (decimal)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, decimal scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, decimal scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, decimal scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Or(Tensor tensor, decimal scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, decimal scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (decimal)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Xor(Tensor tensor, decimal scalar, Tensor result) - { - throw new NotSupportedException(); - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, decimal scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void And(DenseTensor tensor, decimal scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - decimal sum = (decimal)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (decimal)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, decimal scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, decimal scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, decimal scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Or(DenseTensor tensor, decimal scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, decimal scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (decimal)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (decimal)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Xor(DenseTensor tensor, decimal scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - } - internal class DoubleArithmetic : ITensorArithmetic - { - public double One => 1.0; - public double Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, double scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void And(Tensor tensor, double scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - double sum = (double)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (double)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, double scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, double scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, double scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Or(Tensor tensor, double scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, double scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (double)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Xor(Tensor tensor, double scalar, Tensor result) - { - throw new NotSupportedException(); - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, double scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void And(DenseTensor tensor, double scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - double sum = (double)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (double)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, double scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, double scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, double scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Or(DenseTensor tensor, double scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, double scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (double)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (double)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Xor(DenseTensor tensor, double scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - } - internal class FloatArithmetic : ITensorArithmetic - { - public float One => 1.0f; - public float Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, float scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void And(Tensor tensor, float scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - float sum = (float)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (float)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, float scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, float scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, float scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Or(Tensor tensor, float scalar, Tensor result) - { - throw new NotSupportedException(); - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - throw new NotSupportedException(); - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, float scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (float)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - throw new NotSupportedException(); - } - public void Xor(Tensor tensor, float scalar, Tensor result) - { - throw new NotSupportedException(); - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, float scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void And(DenseTensor tensor, float scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - float sum = (float)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (float)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, float scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, float scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, float scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Or(DenseTensor tensor, float scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, float scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (float)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (float)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - throw new NotSupportedException(); - } - public void Xor(DenseTensor tensor, float scalar, DenseTensor result) - { - throw new NotSupportedException(); - } - } - internal class IntArithmetic : ITensorArithmetic - { - public int One => 1; - public int Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - int sum = (int)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (int)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, int scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (int)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - int sum = (int)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (int)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, int scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (int)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (int)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class LongArithmetic : ITensorArithmetic - { - public long One => 1; - public long Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - long sum = (long)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (long)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, long scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (long)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - long sum = (long)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (long)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, long scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (long)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (long)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class SByteArithmetic : ITensorArithmetic - { - public sbyte One => 1; - public sbyte Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - sbyte sum = (sbyte)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (sbyte)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, sbyte scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (sbyte)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - sbyte sum = (sbyte)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (sbyte)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, sbyte scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (sbyte)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (sbyte)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class ShortArithmetic : ITensorArithmetic - { - public short One => 1; - public short Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - short sum = (short)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (short)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)-tensor[indices]; - } - - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, short scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (short)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - short sum = (short)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (short)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)-tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)-tensorSpan[op1Index]; - - } - } - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, short scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (short)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (short)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class UIntArithmetic : ITensorArithmetic - { - public uint One => 1; - public uint Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - uint sum = (uint)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (uint)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, uint scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (uint)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - uint sum = (uint)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (uint)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, uint scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (uint)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (uint)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class ULongArithmetic : ITensorArithmetic - { - public ulong One => 1; - public ulong Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - ulong sum = (ulong)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (ulong)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, ulong scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ulong)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - ulong sum = (ulong)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (ulong)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, ulong scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ulong)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ulong)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } - internal class UShortArithmetic : ITensorArithmetic - { - public ushort One => 1; - public ushort Zero => 0; - - public void Add(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] + right[indices]); - } - - } - public void Add(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] + scalar); - } - - } - public void And(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] & right[indices]); - } - - } - public void And(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] & scalar); - } - - } - public void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - ushort sum = (ushort)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (ushort)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } - } - public void Decrement(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]--; - } - - } - public void Divide(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] / right[indices]); - } - - } - public void Divide(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] / scalar); - } - - } - public void Equals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] == right[indices]; - } - - } - public void GreaterThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] > right[indices]; - } - - } - public void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] >= right[indices]; - } - - } - public void Increment(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices]++; - } - - } - public void LeftShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] << value); - } - - } - public void LessThan(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] < right[indices]; - } - - } - public void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] <= right[indices]; - } - - } - public void Modulo(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] % right[indices]); - } - - } - public void Modulo(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] % scalar); - } - - } - public void Multiply(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] * right[indices]); - } - - } - public void Multiply(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] * scalar); - } - - } - public void NotEquals(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = left[indices] != right[indices]; - } - - } - public void Or(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] | right[indices]); - } - - } - public void Or(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] | scalar); - } - - } - public void RightShift(Tensor tensor, int value, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] >> value); - } - - } - public void Subtract(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] - right[indices]); - } - - } - public void Subtract(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] - scalar); - } - - } - public void UnaryMinus(Tensor tensor, Tensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(Tensor tensor, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)+tensor[indices]; - } - - } - public void Xor(Tensor left, Tensor right, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(left[indices] ^ right[indices]); - } - - } - public void Xor(Tensor tensor, ushort scalar, Tensor result) - { - - Span indices = new Span(new int[result.Rank]); - for (int i = 0; i < result.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - result[indices] = (ushort)(tensor[indices] ^ scalar); - } - - } - - public void Add(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] + rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] + rightSpan[op2Index]); - - } - } - } - public void Add(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] + scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] + scalar); - - } - } - } - public void And(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] & rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] & rightSpan[op2Index]); - - } - } - } - public void And(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] & scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] & scalar); - - } - } - } - public void Contract(DenseTensor left, DenseTensor right, int[] leftAxes, int[] rightAxes, DenseTensor result) - { - var summingDimensions = new int[leftAxes.Length]; - for (int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - ushort sum = (ushort)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (ushort)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } - } - public void Decrement(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]--; - } - } - public void Divide(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] / rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] / rightSpan[op2Index]); - - } - } - } - public void Divide(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] / scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] / scalar); - - } - } - } - public void Equals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] == rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] == rightSpan[op2Index]; - - } - } - } - public void GreaterThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] > rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] > rightSpan[op2Index]; - - } - } - } - public void GreaterThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] >= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] >= rightSpan[op2Index]; - - } - } - } - public void Increment(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i]++; - } - } - public void LeftShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] << value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] << value); - - } - } - } - public void LessThan(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] < rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] < rightSpan[op2Index]; - - } - } - } - public void LessThanOrEqual(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] <= rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] <= rightSpan[op2Index]; - - } - } - } - public void Modulo(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] % rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] % rightSpan[op2Index]); - - } - } - } - public void Modulo(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] % scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] % scalar); - - } - } - } - public void Multiply(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] * rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] * rightSpan[op2Index]); - - } - } - } - public void Multiply(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] * scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] * scalar); - - } - } - } - public void NotEquals(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = leftSpan[i] != rightSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = leftSpan[op1Index] != rightSpan[op2Index]; - - } - } - } - public void Or(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] | rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] | rightSpan[op2Index]); - - } - } - } - public void Or(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] | scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] | scalar); - - } - } - } - public void RightShift(DenseTensor tensor, int value, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] >> value); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] >> value); - - } - } - } - public void Subtract(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] - rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] - rightSpan[op2Index]); - - } - } - } - public void Subtract(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] - scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] - scalar); - - } - } - } - public void UnaryMinus(DenseTensor tensor, DenseTensor result) - { - throw new NotSupportedException(); - } - public void UnaryPlus(DenseTensor tensor, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)+tensorSpan[i]; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)+tensorSpan[op1Index]; - - } - } - } - public void Xor(DenseTensor left, DenseTensor right, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - if ((result.IsReversedStride == left.IsReversedStride) && (result.IsReversedStride == right.IsReversedStride)) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(leftSpan[i] ^ rightSpan[i]); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref left.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - ref int op2Index = ref right.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - !left.IsReversedStride ? left.strides : - right.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - left.IsReversedStride ? left.strides : - right.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(leftSpan[op1Index] ^ rightSpan[op2Index]); - - } - } - } - public void Xor(DenseTensor tensor, ushort scalar, DenseTensor result) - { - - var resultSpan = result.Buffer.Span; - var tensorSpan = tensor.Buffer.Span; - if (result.IsReversedStride == tensor.IsReversedStride) - { - for (int i = 0; i < resultSpan.Length; i++) - { - resultSpan[i] = (ushort)(tensorSpan[i] ^ scalar); - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref result.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref tensor.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !result.IsReversedStride ? result.strides : - tensor.strides; - var columnMajorStrides = result.IsReversedStride ? result.strides : - tensor.strides; - for (;rowMajorIndex < resultSpan.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - resultSpan[resultIndex] = (ushort)(tensorSpan[op1Index] ^ scalar); - - } - } - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.tt b/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.tt deleted file mode 100644 index 91efa47c1ab76..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorArithmetic.tt +++ /dev/null @@ -1,237 +0,0 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ output extension=".cs" #> -<#@ include file="TensorTemplate.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - internal interface ITensorArithmetic - { - T One { get; } - T Zero { get; } -<# foreach (MethodConfiguration method in methodConfiguration) { #> - <#= method.GetResultMethodSignature("Tensor", "T")#>; -<# } #> - } - - internal static class TensorArithmetic - { - public static ITensorArithmetic Instance => TensorArithmetic.GetArithmetic(); - } - - internal static class TensorArithmetic - { - public static ITensorArithmetic GetArithmetic() - { -<# foreach (TypeConfiguration type in typeConfiguration) { #> - <#=GenerateIfStatementHeader(type)#> - { - return (ITensorArithmetic)new <#=type.ClassPrefix#>Arithmetic(); - } -<# } #> - return null; - } - } - -<# foreach (TypeConfiguration type in typeConfiguration) { #> - internal class <#=type.ClassPrefix#>Arithmetic : ITensorArithmetic<<#=type.TypeName#>> - { - public <#=type.TypeName#> One => <#=type.OneLiteral#>; - public <#=type.TypeName#> Zero => <#=type.ZeroLiteral#>; - -<# foreach (MethodConfiguration method in methodConfiguration) { #> - public <#= method.GetResultMethodSignature("Tensor", type.TypeName)#> - { -<# if ((method.IsNumeric && !type.SupportsNumeric) || (method.IsBitwise && !type.SupportsBitwise) || (type.UnsupportedMethods.Contains(method.MethodName))) { #> - throw new NotSupportedException(); -<# } else if (method.Operator != null) { #> - - Span indices = new Span(new int[result.Rank]); - for(int i = 0; i < <#= method.ResultName #>.Length; i++) - { - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, i, indices); - <#=method.GetElementOperation(type.TypeName, "[indices]")#>; - } - -<# } else if (method.MethodName == "Contract") {#> - var leftIndices = new int[left.Rank]; - var rightIndices = new int[right.Rank]; - var resultIndices = new int[result.Rank]; - - var summingDimensions = new int[leftAxes.Length]; - for(int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - for (int resultIndex = 0; resultIndex < result.Length; resultIndex++) - { - <#=type.TypeName#> sum = (<#=type.TypeName#>)0; - - ArrayUtilities.GetIndices(result.strides, result.IsReversedStride, resultIndex, resultIndices); - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - // todo, make this more efficient - ArrayUtilities.GetIndices(left.strides, left.IsReversedStride, leftIndex, leftIndices); - ArrayUtilities.GetIndices(right.strides, right.IsReversedStride, rightIndex, rightIndices); - - sum += (<#=type.TypeName#>)(left[leftIndices] * right[rightIndices]); - } - - result[resultIndices] = sum; - } -<# } #> - } -<# } #> - -<# foreach (MethodConfiguration method in methodConfiguration) { #> - public <#= method.GetResultMethodSignature("DenseTensor", type.TypeName)#> - { -<# if ((method.IsNumeric && !type.SupportsNumeric) || (method.IsBitwise && !type.SupportsBitwise) || (type.UnsupportedMethods.Contains(method.MethodName))) { #> - throw new NotSupportedException(); -<# } else if (method.Operator != null) { #> - -<# if (method.MethodType == MethodType.UnaryInPlace) { #> - var <#=method.ResultName #>Span = <#=method.ResultName #>.Buffer.Span; - var <#=method.Op1Name #>Span = <#=method.Op1Name #>.Buffer.Span; - for(int i = 0; i < <#=method.ResultName #>Span.Length; i++) - { - <#=method.GetElementOperation(type.TypeName, "Span[i]")#>; - } -<# } else {#> - var <#=method.ResultName #>Span = <#=method.ResultName #>.Buffer.Span; - var <#=method.Op1Name #>Span = <#=method.Op1Name #>.Buffer.Span; -<# if ((method.MethodType == MethodType.Binary) || (method.MethodType == MethodType.Comparison)) {#> - var <#=method.Op2Name #>Span = <#=method.Op2Name #>.Buffer.Span; -<# } #> - if <#= method.GetLinearOperationCheck() #> - { - for(int i = 0; i < <#= method.ResultName #>Span.Length; i++) - { - <#=method.GetElementOperation(type.TypeName, "Span[i]")#>; - } - } - else - { - int rowMajorIndex = 0; - int colMajorIndex = 0; - - ref int resultIndex = ref <#= method.ResultName #>.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - ref int op1Index = ref <#= method.Op1Name #>.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - -<# if ((method.MethodType == MethodType.Binary) || (method.MethodType == MethodType.Comparison)) {#> - ref int op2Index = ref <#= method.Op2Name #>.IsReversedStride ? ref colMajorIndex : ref rowMajorIndex; - - var rowMajorStrides = !<#= method.ResultName #>.IsReversedStride ? <#= method.ResultName #>.strides : - !<#= method.Op1Name #>.IsReversedStride ? <#= method.Op1Name #>.strides : - <#= method.Op2Name #>.strides; - var columnMajorStrides = <#= method.ResultName #>.IsReversedStride ? <#= method.ResultName #>.strides : - <#= method.Op1Name #>.IsReversedStride ? <#= method.Op1Name #>.strides : - <#= method.Op2Name #>.strides; -<# } else {#> - var rowMajorStrides = !<#= method.ResultName #>.IsReversedStride ? <#= method.ResultName #>.strides : - <#= method.Op1Name #>.strides; - var columnMajorStrides = <#= method.ResultName #>.IsReversedStride ? <#= method.ResultName #>.strides : - <#= method.Op1Name #>.strides; -<# } #> - for(;rowMajorIndex < <#= method.ResultName #>Span.Length; rowMajorIndex++) - { - colMajorIndex = ArrayUtilities.TransformIndexByStrides(rowMajorIndex, rowMajorStrides, false, columnMajorStrides); - - <#=method.GetElementOperation(type.TypeName, "Span[resultIndex]", "Span[op1Index]", "Span[op2Index]")#>; - - } - } -<# } #> -<# } else if (method.MethodName == "Contract") {#> - var summingDimensions = new int[leftAxes.Length]; - for(int i = 0; i < leftAxes.Length; i++) - { - summingDimensions[i] = left.dimensions[leftAxes[i]]; - } - - var summingStrides = ArrayUtilities.GetStrides(summingDimensions); - int summingLength = (int)ArrayUtilities.GetProduct(summingDimensions); - - var resultStrides = result.strides; - - // translates from result index to left non-summing dimensions' index portion - // since left non-summing dimensions are given precedence in result, the end is zero-padded - int[] leftNonSummingStrides = new int[result.Rank]; - - // translates from summing index to left summing dimensions' index portion - int[] leftSummingStrides = new int[leftAxes.Length]; - ArrayUtilities.SplitStrides(left.strides, leftAxes, leftNonSummingStrides, 0, leftSummingStrides, 0); - - // translates from result index to right non-summing dimensions' index portion - int[] rightNonSummingStrides = new int[result.Rank]; - // right non-summing dimensions appear after left non-summing dimensions. - int rightNonSummingStridesOffset = (left.Rank - leftAxes.Length); - - // translates from summing index to right summing dimensions' index portion - int[] rightSummingStrides = new int[rightAxes.Length]; - ArrayUtilities.SplitStrides(right.strides, rightAxes, rightNonSummingStrides, rightNonSummingStridesOffset, rightSummingStrides, 0); - - var resultSpan = result.Buffer.Span; - var leftSpan = left.Buffer.Span; - var rightSpan = right.Buffer.Span; - - for (int resultIndex = 0; resultIndex < resultSpan.Length; resultIndex++) - { - <#=type.TypeName#> sum = (<#=type.TypeName#>)0; - - int leftIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, leftNonSummingStrides); - int rightIndexNonSumming = ArrayUtilities.TransformIndexByStrides(resultIndex, resultStrides, result.IsReversedStride, rightNonSummingStrides); - - for (int summingIndex = 0; summingIndex < summingLength; summingIndex++) - { - int leftIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, leftSummingStrides); - int rightIndexSumming = ArrayUtilities.TransformIndexByStrides(summingIndex, summingStrides, false, rightSummingStrides); - - int leftIndex = leftIndexNonSumming + leftIndexSumming; - int rightIndex = rightIndexNonSumming + rightIndexSumming; - - sum += (<#=type.TypeName#>)(leftSpan[leftIndex] * rightSpan[rightIndex]); - } - - resultSpan[resultIndex] = sum; - } -<# } #> - } -<# } #> - } -<# } #> -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorExtensions.cs b/src/libraries/System.Numerics.Tensors/tests/TensorExtensions.cs deleted file mode 100644 index 2aa79f0e12058..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - public static partial class TensorExtensions - { - private static int[] s_zeroArray = new[] { 0 }; - private static int[] s_oneArray = new[] { 1 }; - - internal static Tensor MatrixMultiply(this Tensor left, Tensor right) - { - if (left.Rank != 2) - { - throw new InvalidOperationException($"{nameof(MatrixMultiply)} is only valid for a {nameof(Tensor)} of {nameof(left.Rank)} 2."); - } - - if (right.Rank != 2) - { - throw new ArgumentException($"{nameof(Tensor)} {nameof(right)} must have {nameof(left.Rank)} 2.", nameof(right)); - } - - if (left.dimensions[1] != right.dimensions[0]) - { - throw new ArgumentException($"{nameof(Tensor)} {nameof(right)} must have first dimension of {left.dimensions[1]}.", nameof(right)); - } - - return TensorOperations.Contract(left, right, s_oneArray, s_zeroArray); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorOperations.cs b/src/libraries/System.Numerics.Tensors/tests/TensorOperations.cs deleted file mode 100644 index 009ad006b88c5..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorOperations.cs +++ /dev/null @@ -1,738 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - public static partial class TensorOperations - { - internal static void ValidateBinaryArgs(Tensor left, Tensor right) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < left.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - } - } - - internal static void ValidateBinaryArgs(Tensor left, Tensor right, Tensor result) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank != result.Rank || left.Length != result.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(result)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static void ValidateBinaryArgs(Tensor left, Tensor right, Tensor result) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank != result.Rank || left.Length != result.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(result)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static void ValidateArgs(Tensor tensor) - { - if (tensor.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(tensor)); - } - } - - internal static void ValidateArgs(Tensor tensor, Tensor result) - { - if (tensor.Rank != result.Rank || tensor.Length != result.Length) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - - if (tensor.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(tensor)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (tensor.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static int[] ValidateContractArgs(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes) - { - if (leftAxes == null) - { - throw new ArgumentNullException(nameof(left)); - } - - if (rightAxes == null) - { - throw new ArgumentNullException(nameof(left)); - } - - if (leftAxes.Length != rightAxes.Length) - { - throw new ArgumentException($"{nameof(leftAxes)} and {nameof(rightAxes)} must have the same length, but were {leftAxes.Length} and {rightAxes.Length}, respectively."); - } - - for (int i = 0; i < leftAxes.Length; i++) - { - var leftAxis = leftAxes[i]; - - if (leftAxis >= left.Rank) - { - throw new ArgumentOutOfRangeException($"{nameof(leftAxes)}[{i}] was set to axis index {leftAxis} which exceeds the Rank of {left}."); - } - - var leftDimension = left.dimensions[leftAxis]; - - var rightAxis = rightAxes[i]; - - if (rightAxis >= right.Rank) - { - throw new ArgumentOutOfRangeException($"{nameof(rightAxes)}[{i}] was set to axis index {rightAxis} which exceeds the Rank of {right}."); - } - - var rightDimension = right.dimensions[rightAxis]; - - if (leftDimension != rightDimension) - { - throw new ArgumentOutOfRangeException($"Tensors may only be contracted on axes of the same length, but {nameof(leftAxes)} index {i} was length {leftDimension} and {nameof(rightAxes)} index {i} was length {rightDimension}."); - } - } - - var leftNonSummingDimensions = left.Rank - leftAxes.Length; - var rightNonSummingDimensions = right.Rank - rightAxes.Length; - var resultDimensions = new int[leftNonSummingDimensions + rightNonSummingDimensions]; - int dimensionsIndex = 0; - - Action, int[]> fillDimensions = (tensor, axes) => - { - for (int i = 0; i < tensor.Rank; i++) - { - var skip = false; - foreach (var contractionIndex in axes) - { - if (contractionIndex == i) - { - skip = true; - break; - } - } - - if (!skip) - { - resultDimensions[dimensionsIndex++] = tensor.dimensions[i]; - } - } - }; - - fillDimensions(left, leftAxes); - fillDimensions(right, rightAxes); - - return resultDimensions; - } - - internal static int[] ValidateContractArgs(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var expectedDimensions = ValidateContractArgs(left, right, leftAxes, rightAxes); - - if (result.Rank != expectedDimensions.Length) - { - throw new ArgumentException($"{nameof(result)} should have {expectedDimensions.Length} dimensions but had {result.Rank}."); - } - - for (int i = 0; i < expectedDimensions.Length; i++) - { - if (result.dimensions[i] != expectedDimensions[i]) - { - throw new ArgumentException($"{nameof(result)} dimension {i} should be {expectedDimensions[i]} but was {result.dimensions[i]}."); - } - } - - return expectedDimensions; - } - - internal static void Add(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Add(left, right, result); - } - - internal static Tensor Add(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Add(left, right, result); - - return result; - } - - internal static void Add(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Add(tensor, scalar, result); - } - - internal static Tensor Add(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Add(tensor, scalar, result); - - return result; - } - - internal static void And(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.And(left, right, result); - } - - internal static Tensor And(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.And(left, right, result); - - return result; - } - - internal static void And(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.And(tensor, scalar, result); - } - - internal static Tensor And(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.And(tensor, scalar, result); - - return result; - } - - internal static void Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - ValidateContractArgs(left, right, leftAxes, rightAxes, result); - - TensorArithmetic.Instance.Contract(left, right, leftAxes, rightAxes, result); - } - - internal static Tensor Contract(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes) - { - var resultDimensions = ValidateContractArgs(left, right, leftAxes, rightAxes); - - var result = left.CloneEmpty(resultDimensions); - - TensorArithmetic.Instance.Contract(left, right, leftAxes, rightAxes, result); - - return result; - } - - internal static void Decrement(Tensor tensor, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Decrement(tensor, result); - } - - internal static Tensor Decrement(Tensor tensor) - { - ValidateArgs(tensor); - - var result = tensor.Clone(); - - TensorArithmetic.Instance.Decrement(tensor, result); - - return result; - } - - internal static void Divide(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Divide(left, right, result); - } - - internal static Tensor Divide(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Divide(left, right, result); - - return result; - } - - internal static void Divide(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Divide(tensor, scalar, result); - } - - internal static Tensor Divide(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Divide(tensor, scalar, result); - - return result; - } - - internal static void Equals(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Equals(left, right, result); - } - - internal static Tensor Equals(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Equals(left, right, result); - - return result; - } - - internal static void GreaterThan(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.GreaterThan(left, right, result); - } - - internal static Tensor GreaterThan(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.GreaterThan(left, right, result); - - return result; - } - - internal static void GreaterThanOrEqual(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.GreaterThanOrEqual(left, right, result); - } - - internal static Tensor GreaterThanOrEqual(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.GreaterThanOrEqual(left, right, result); - - return result; - } - - internal static void Increment(Tensor tensor, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Increment(tensor, result); - } - - internal static Tensor Increment(Tensor tensor) - { - ValidateArgs(tensor); - - var result = tensor.Clone(); - - TensorArithmetic.Instance.Increment(tensor, result); - - return result; - } - - internal static void LeftShift(Tensor tensor, int value, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.LeftShift(tensor, value, result); - } - - internal static Tensor LeftShift(Tensor tensor, int value) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.LeftShift(tensor, value, result); - - return result; - } - - internal static void LessThan(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.LessThan(left, right, result); - } - - internal static Tensor LessThan(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.LessThan(left, right, result); - - return result; - } - - internal static void LessThanOrEqual(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.LessThanOrEqual(left, right, result); - } - - internal static Tensor LessThanOrEqual(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.LessThanOrEqual(left, right, result); - - return result; - } - - internal static void Modulo(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Modulo(left, right, result); - } - - internal static Tensor Modulo(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Modulo(left, right, result); - - return result; - } - - internal static void Modulo(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Modulo(tensor, scalar, result); - } - - internal static Tensor Modulo(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Modulo(tensor, scalar, result); - - return result; - } - - internal static void Multiply(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Multiply(left, right, result); - } - - internal static Tensor Multiply(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Multiply(left, right, result); - - return result; - } - - internal static void Multiply(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Multiply(tensor, scalar, result); - } - - internal static Tensor Multiply(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Multiply(tensor, scalar, result); - - return result; - } - - internal static void NotEquals(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.NotEquals(left, right, result); - } - - internal static Tensor NotEquals(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.NotEquals(left, right, result); - - return result; - } - - internal static void Or(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Or(left, right, result); - } - - internal static Tensor Or(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Or(left, right, result); - - return result; - } - - internal static void Or(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Or(tensor, scalar, result); - } - - internal static Tensor Or(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Or(tensor, scalar, result); - - return result; - } - - internal static void RightShift(Tensor tensor, int value, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.RightShift(tensor, value, result); - } - - internal static Tensor RightShift(Tensor tensor, int value) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.RightShift(tensor, value, result); - - return result; - } - - internal static void Subtract(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Subtract(left, right, result); - } - - internal static Tensor Subtract(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Subtract(left, right, result); - - return result; - } - - internal static void Subtract(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Subtract(tensor, scalar, result); - } - - internal static Tensor Subtract(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Subtract(tensor, scalar, result); - - return result; - } - - internal static void UnaryMinus(Tensor tensor, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.UnaryMinus(tensor, result); - } - - internal static Tensor UnaryMinus(Tensor tensor) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.UnaryMinus(tensor, result); - - return result; - } - - internal static void UnaryPlus(Tensor tensor, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.UnaryPlus(tensor, result); - } - - internal static Tensor UnaryPlus(Tensor tensor) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.UnaryPlus(tensor, result); - - return result; - } - - internal static void Xor(Tensor left, Tensor right, Tensor result) - { - ValidateBinaryArgs(left, right, result); - - TensorArithmetic.Instance.Xor(left, right, result); - } - - internal static Tensor Xor(Tensor left, Tensor right) - { - ValidateBinaryArgs(left, right); - - var result = left.CloneEmpty(); - - TensorArithmetic.Instance.Xor(left, right, result); - - return result; - } - - internal static void Xor(Tensor tensor, T scalar, Tensor result) - { - ValidateArgs(tensor, result); - - TensorArithmetic.Instance.Xor(tensor, scalar, result); - } - - internal static Tensor Xor(Tensor tensor, T scalar) - { - ValidateArgs(tensor); - - var result = tensor.CloneEmpty(); - - TensorArithmetic.Instance.Xor(tensor, scalar, result); - - return result; - } - - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorOperations.tt b/src/libraries/System.Numerics.Tensors/tests/TensorOperations.tt deleted file mode 100644 index 6b96c0bb554a5..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorOperations.tt +++ /dev/null @@ -1,239 +0,0 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> -<#@ assembly name="System.Core" #> -<#@ output extension=".cs" #> -<#@ include file="TensorTemplate.ttinclude" #>// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Numerics.Tensors -{ - public static partial class TensorOperations - { - internal static void ValidateBinaryArgs(Tensor left, Tensor right) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < left.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - } - } - - internal static void ValidateBinaryArgs(Tensor left, Tensor right, Tensor result) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank != result.Rank || left.Length != result.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(result)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static void ValidateBinaryArgs(Tensor left, Tensor right, Tensor result) - { - if (left.Rank != right.Rank || left.Length != right.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.Rank != result.Rank || left.Length != result.Length) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(result)); - } - - if (left.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(left)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (left.dimensions[i] != right.dimensions[i]) - { - throw new ArgumentException("Operands must have matching dimensions", nameof(right)); - } - - if (left.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static void ValidateArgs(Tensor tensor) - { - if (tensor.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(tensor)); - } - } - - internal static void ValidateArgs(Tensor tensor, Tensor result) - { - if (tensor.Rank != result.Rank || tensor.Length != result.Length) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - - if (tensor.Rank == 0) - { - throw new ArgumentException($"Cannot operate on Tensor with {nameof(Tensor.Rank)} of 0.", nameof(tensor)); - } - - for (int i = 0; i < result.Rank; i++) - { - if (tensor.dimensions[i] != result.dimensions[i]) - { - throw new ArgumentException("Operands and result must have matching dimensions", nameof(result)); - } - } - } - - internal static int[] ValidateContractArgs(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes) - { - if (leftAxes == null) - { - throw new ArgumentNullException(nameof(left)); - } - - if (rightAxes == null) - { - throw new ArgumentNullException(nameof(left)); - } - - if (leftAxes.Length != rightAxes.Length) - { - throw new ArgumentException($"{nameof(leftAxes)} and {nameof(rightAxes)} must have the same length, but were {leftAxes.Length} and {rightAxes.Length}, respectively."); - } - - for (int i = 0; i < leftAxes.Length; i++) - { - var leftAxis = leftAxes[i]; - - if (leftAxis >= left.Rank) - { - throw new ArgumentOutOfRangeException($"{nameof(leftAxes)}[{i}] was set to axis index {leftAxis} which exceeds the Rank of {left}."); - } - - var leftDimension = left.dimensions[leftAxis]; - - var rightAxis = rightAxes[i]; - - if (rightAxis >= right.Rank) - { - throw new ArgumentOutOfRangeException($"{nameof(rightAxes)}[{i}] was set to axis index {rightAxis} which exceeds the Rank of {right}."); - } - - var rightDimension = right.dimensions[rightAxis]; - - if (leftDimension != rightDimension) - { - throw new ArgumentOutOfRangeException($"Tensors may only be contracted on axes of the same length, but {nameof(leftAxes)} index {i} was length {leftDimension} and {nameof(rightAxes)} index {i} was length {rightDimension}."); - } - } - - var leftNonSummingDimensions = left.Rank - leftAxes.Length; - var rightNonSummingDimensions = right.Rank - rightAxes.Length; - var resultDimensions = new int[leftNonSummingDimensions + rightNonSummingDimensions]; - int dimensionsIndex = 0; - - Action, int[]> fillDimensions = (tensor, axes) => - { - for (int i = 0; i < tensor.Rank; i++) - { - var skip = false; - foreach (var contractionIndex in axes) - { - if (contractionIndex == i) - { - skip = true; - break; - } - } - - if (!skip) - { - resultDimensions[dimensionsIndex++] = tensor.dimensions[i]; - } - } - }; - - fillDimensions(left, leftAxes); - fillDimensions(right, rightAxes); - - return resultDimensions; - } - - internal static int[] ValidateContractArgs(Tensor left, Tensor right, int[] leftAxes, int[] rightAxes, Tensor result) - { - var expectedDimensions = ValidateContractArgs(left, right, leftAxes, rightAxes); - - if (result.Rank != expectedDimensions.Length) - { - throw new ArgumentException($"{nameof(result)} should have {expectedDimensions.Length} dimensions but had {result.Rank}."); - } - - for (int i = 0; i < expectedDimensions.Length; i++) - { - if (result.dimensions[i] != expectedDimensions[i]) - { - throw new ArgumentException($"{nameof(result)} dimension {i} should be {expectedDimensions[i]} but was {result.dimensions[i]}."); - } - } - - return expectedDimensions; - } - -<# foreach (MethodConfiguration method in methodConfiguration) { #> - internal static <#= method.GetGenericResultMethodSignature("Tensor", "T")#> - { - <#= method.GetValidationMethod(true) #> - - TensorArithmetic.Instance.<#=method.MethodName#>(<#=method.GetCallArguments()#>, <#= method.ResultName #>); - } - - internal static <#= method.GetGenericMethodSignature("Tensor", "T")#> - { - <#= method.GetValidationMethod(false) #> - - var <#= method.ResultName #> = <#=method.InitializeResult("T")#>; - - TensorArithmetic.Instance.<#=method.MethodName#>(<#=method.GetCallArguments()#>, <#= method.ResultName #>); - - return <#= method.ResultName #>; - } - -<# } #> - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorPrimitivesTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitivesTests.cs new file mode 100644 index 0000000000000..1e751543831c3 --- /dev/null +++ b/src/libraries/System.Numerics.Tensors/tests/TensorPrimitivesTests.cs @@ -0,0 +1,633 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +#pragma warning disable xUnit1025 // reporting duplicate test cases due to not distinguishing 0.0 from -0.0 + +namespace System.Numerics.Tensors.Tests +{ + public static class TensorPrimitivesTests + { + private const int TensorSize = 512; + + private const int MismatchedTensorSize = 2; + + private static readonly Random s_random = new Random(20230828); + + private static float[] CreateTensor(int size) + { + return new float[size]; + } + + private static float[] CreateAndFillTensor(int size) + { + float[] tensor = CreateTensor(size); + FillTensor(tensor); + return tensor; + } + + private static void FillTensor(float[] tensor) + { + for (int i = 0; i < tensor.Length; i++) + { + tensor[i] = NextSingle(); + } + } + + private static float NextSingle() + { +#if NETCOREAPP + return s_random.NextSingle(); +#else + return (float)s_random.NextDouble(); +#endif + } + + [Fact] + public static void AddTwoTensors() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Add(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] + y[i]), destination[i]); + } + } + + [Fact] + public static void AddTwoTensors_ThrowsForMismatchedLengths() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.Add(x, y, destination)); + } + + [Fact] + public static void AddTwoTensors_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Add(x, y, destination)); + } + + [Fact] + public static void AddTensorAndScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Add(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] + y), destination[i]); + } + } + + [Fact] + public static void AddTensorAndScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Add(x, y, destination)); + } + + [Fact] + public static void SubtractTwoTensors() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Subtract(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] - y[i]), destination[i]); + } + } + + [Fact] + public static void SubtractTwoTensors_ThrowsForMismatchedLengths() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.Subtract(x, y, destination)); + } + + [Fact] + public static void SubtractTwoTensors_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Subtract(x, y, destination)); + } + + [Fact] + public static void SubtractTensorAndScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Subtract(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] - y), destination[i]); + } + } + + [Fact] + public static void SubtractTensorAndScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Subtract(x, y, destination)); + } + + [Fact] + public static void MultiplyTwoTensors() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Multiply(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] * y[i]), destination[i]); + } + } + + [Fact] + public static void MultiplyTwoTensors_ThrowsForMismatchedLengths() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.Multiply(x, y, destination)); + } + + [Fact] + public static void MultiplyTwoTensors_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Multiply(x, y, destination)); + } + + [Fact] + public static void MultiplyTensorAndScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Multiply(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] * y), destination[i]); + } + } + + [Fact] + public static void MultiplyTensorAndScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Multiply(x, y, destination)); + } + + [Fact] + public static void DivideTwoTensors() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Divide(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] / y[i]), destination[i]); + } + } + + [Fact] + public static void DivideTwoTensors_ThrowsForMismatchedLengths() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.Divide(x, y, destination)); + } + + [Fact] + public static void DivideTwoTensors_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Divide(x, y, destination)); + } + + [Fact] + public static void DivideTensorAndScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Divide(x, y, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] / y), destination[i]); + } + } + + [Fact] + public static void DivideTensorAndScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Divide(x, y, destination)); + } + + [Fact] + public static void NegateTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Negate(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(-x[i], destination[i]); + } + } + + [Fact] + public static void NegateTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Negate(x, destination)); + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithThirdTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] multiplier = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.AddMultiply(x, y, multiplier, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] + y[i]) * multiplier[i], destination[i]); + } + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithThirdTensor_ThrowsForMismatchedLengths_x_y() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] multiplier = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.AddMultiply(x, y, multiplier, destination)); + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithThirdTensor_ThrowsForMismatchedLengths_x_multiplier() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] multiplier = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.AddMultiply(x, y, multiplier, destination)); + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithThirdTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] multiplier = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.AddMultiply(x, y, multiplier, destination)); + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float multiplier = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.AddMultiply(x, y, multiplier, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] + y[i]) * multiplier, destination[i]); + } + } + + [Fact] + public static void AddTwoTensorsAndMultiplyWithScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float multiplier = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.AddMultiply(x, y, multiplier, destination)); + } + + [Fact] + public static void AddTensorAndScalarAndMultiplyWithTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] multiplier = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.AddMultiply(x, y, multiplier, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] + y) * multiplier[i], destination[i]); + } + } + + [Fact] + public static void AddTensorAndScalarAndMultiplyWithTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] multiplier = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.AddMultiply(x, y, multiplier, destination)); + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithThirdTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] addend = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.MultiplyAdd(x, y, addend, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] * y[i]) + addend[i], destination[i]); + } + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithThirdTensor_ThrowsForMismatchedLengths_x_y() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(MismatchedTensorSize); + float[] addend = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.MultiplyAdd(x, y, addend, destination)); + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithThirdTensor_ThrowsForMismatchedLengths_x_multiplier() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] addend = CreateAndFillTensor(MismatchedTensorSize); + float[] destination = CreateTensor(TensorSize); + + Assert.Throws(() => TensorPrimitives.MultiplyAdd(x, y, addend, destination)); + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithThirdTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float[] addend = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.MultiplyAdd(x, y, addend, destination)); + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithScalar() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float addend = NextSingle(); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.MultiplyAdd(x, y, addend, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] * y[i]) + addend, destination[i]); + } + } + + [Fact] + public static void MultiplyTwoTensorsAndAddWithScalar_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] y = CreateAndFillTensor(TensorSize); + float addend = NextSingle(); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.MultiplyAdd(x, y, addend, destination)); + } + + [Fact] + public static void MultiplyTensorAndScalarAndAddWithTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] addend = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.MultiplyAdd(x, y, addend, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal((x[i] * y) + addend[i], destination[i]); + } + } + + [Fact] + public static void MultiplyTensorAndScalarAndAddWithTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float y = NextSingle(); + float[] addend = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.MultiplyAdd(x, y, addend, destination)); + } + + [Fact] + public static void ExpTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Exp(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(MathF.Exp(x[i]), destination[i]); + } + } + + [Fact] + public static void ExpTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Exp(x, destination)); + } + + [Fact] + public static void LogTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Log(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(MathF.Log(x[i]), destination[i]); + } + } + + [Fact] + public static void LogTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Log(x, destination)); + } + + [Fact] + public static void CoshTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Cosh(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(MathF.Cosh(x[i]), destination[i]); + } + } + + [Fact] + public static void CoshTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Cosh(x, destination)); + } + + [Fact] + public static void SinhTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Sinh(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(MathF.Sinh(x[i]), destination[i]); + } + } + + [Fact] + public static void SinhTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Sinh(x, destination)); + } + + [Fact] + public static void TanhTensor() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(TensorSize); + + TensorPrimitives.Tanh(x, destination); + + for (int i = 0; i < TensorSize; i++) + { + Assert.Equal(MathF.Tanh(x[i]), destination[i]); + } + } + + [Fact] + public static void TanhTensor_ThrowsForTooShortDestination() + { + float[] x = CreateAndFillTensor(TensorSize); + float[] destination = CreateTensor(MismatchedTensorSize); + + Assert.Throws(() => TensorPrimitives.Tanh(x, destination)); + } + } +} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTemplate.ttinclude b/src/libraries/System.Numerics.Tensors/tests/TensorTemplate.ttinclude deleted file mode 100644 index 9448791a5db6c..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTemplate.ttinclude +++ /dev/null @@ -1,328 +0,0 @@ -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#+ - public class TypeConfiguration - { - public TypeConfiguration(string typeName, string classPrefix = null, string oneLiteral = "1", string zeroLiteral = "0", bool supportsNumeric = true, bool supportsBitwise = true, IEnumerable unsupportedMethods = null) - { - TypeName = typeName; - ClassPrefix = classPrefix ?? char.ToUpper(typeName[0]) + typeName.Substring(1); - OneLiteral = oneLiteral; - ZeroLiteral = zeroLiteral; - SupportsNumeric = supportsNumeric; - SupportsBitwise = supportsBitwise; - UnsupportedMethods = new HashSet(unsupportedMethods ?? Enumerable.Empty()); - } - - public string TypeName { get; } - public string ClassPrefix { get; } - public string OneLiteral { get; } - public string ZeroLiteral { get; } - - public bool SupportsNumeric { get; } - public bool SupportsBitwise { get; } - public ISet UnsupportedMethods { get; } - } - - public string GenerateIfStatementHeader(TypeConfiguration type) - { - string keyword = (type == typeConfiguration[0]) ? "if" : "else if"; - return $"{keyword} (typeof(T) == typeof({type.TypeName}))"; - } - - public TypeConfiguration[] typeConfiguration = new [] - { - new TypeConfiguration("bool", oneLiteral:"true", zeroLiteral:"false", supportsNumeric: false, unsupportedMethods: new[] {"LeftShift", "RightShift"}), - new TypeConfiguration("byte"), - new TypeConfiguration("char", oneLiteral:"(char)1", zeroLiteral:"(char)0"), - new TypeConfiguration("decimal", supportsBitwise: false), - new TypeConfiguration("double", oneLiteral:"1.0", supportsBitwise: false), - new TypeConfiguration("float", oneLiteral:"1.0f", supportsBitwise: false), - new TypeConfiguration("int"), - new TypeConfiguration("long"), - new TypeConfiguration("sbyte", classPrefix:"SByte"), - new TypeConfiguration("short"), - new TypeConfiguration("uint", classPrefix:"UInt", unsupportedMethods: new[] {"UnaryMinus"}), - new TypeConfiguration("ulong", classPrefix:"ULong", unsupportedMethods: new[] {"UnaryMinus"}), - new TypeConfiguration("ushort", classPrefix:"UShort", unsupportedMethods: new[] {"UnaryMinus"}) - }; - - public enum MethodType - { - Unary, - UnaryInPlace, - BinaryScalar, - BinaryInt, - Binary, - Comparison, - Contraction - } - - public class MethodConfiguration - { - public MethodConfiguration(string methodName, MethodType methodType, string op = null, bool isNumeric = false, bool isBitwise = false) - { - MethodName = methodName; - MethodType = methodType; - Operator = op; - IsNumeric = isNumeric; - IsBitwise = isBitwise; - } - - public string ResultName => "result"; - - public string Op1Name - { - get - { - switch (MethodType) - { - case MethodType.Unary: - case MethodType.UnaryInPlace: - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - return "tensor"; - case MethodType.Binary: - case MethodType.Comparison: - case MethodType.Contraction: - return "left"; - default: - throw new ArgumentException(); - }; - } - } - - public string Op2Name - { - get - { - switch (MethodType) - { - case MethodType.BinaryScalar: - return "scalar"; - case MethodType.BinaryInt: - return "value"; - case MethodType.Binary: - case MethodType.Comparison: - case MethodType.Contraction: - return "right"; - case MethodType.Unary: - case MethodType.UnaryInPlace: - default: - throw new ArgumentException(); - }; - } - } - - public string MethodName { get; } - public MethodType MethodType { get; } - public string Operator { get; } - - public string GetGenericMethodSignature(string tensorType, string genericType) - { - var resultType = GetResultType(tensorType, genericType); - var arguments = GetMethodArguments(tensorType, genericType); - - return $"{resultType} {MethodName}<{genericType}>({arguments})"; - } - - public string GetGenericResultMethodSignature(string tensorType, string genericType) - { - var resultType = GetResultType(tensorType, genericType); - var arguments = GetMethodArguments(tensorType, genericType); - - return $"void {MethodName}<{genericType}>({arguments}, {resultType} {ResultName})"; - } - - public string GetResultMethodSignature(string tensorType, string genericType) - { - var resultType = GetResultType(tensorType, genericType); - var arguments = GetMethodArguments(tensorType, genericType); - - return $"void {MethodName}({arguments}, {resultType} {ResultName})"; - } - - public string GetMethodArguments(string tensorType, string genericType) - { - switch (MethodType) - { - case MethodType.Unary: - case MethodType.UnaryInPlace: - return $"{tensorType}<{genericType}> {Op1Name}"; - case MethodType.BinaryScalar: - return $"{tensorType}<{genericType}> {Op1Name}, {genericType} {Op2Name}"; - case MethodType.BinaryInt: - return $"{tensorType}<{genericType}> {Op1Name}, int {Op2Name}"; - case MethodType.Binary: - case MethodType.Comparison: - return $"{tensorType}<{genericType}> {Op1Name}, {tensorType}<{genericType}> {Op2Name}"; - case MethodType.Contraction: - return $"{tensorType}<{genericType}> {Op1Name}, {tensorType}<{genericType}> {Op2Name}, int[] leftAxes, int[] rightAxes"; - default: - throw new ArgumentException(); - } - } - - public string GetCallArguments() - { - switch (MethodType) - { - case MethodType.Unary: - case MethodType.UnaryInPlace: - return $"{Op1Name}"; - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - case MethodType.Binary: - case MethodType.Comparison: - return $"{Op1Name}, {Op2Name}"; - case MethodType.Contraction: - return "left, right, leftAxes, rightAxes"; - default: - throw new ArgumentException(); - } - } - - public string GetValidationMethod(bool includeResult) - { - var suffix = includeResult ? ", result" : ""; - switch (MethodType) - { - case MethodType.Unary: - case MethodType.UnaryInPlace: - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - return $"ValidateArgs({Op1Name}{suffix});"; - case MethodType.Binary: - case MethodType.Comparison: - return $"ValidateBinaryArgs({Op1Name}, {Op2Name}{suffix});"; - case MethodType.Contraction: - return $"var resultDimensions = ValidateContractArgs({Op1Name}, {Op2Name}, leftAxes, rightAxes{suffix});"; - default: - throw new ArgumentException(); - } - } - - public string GetResultType(string tensorType, string typeName) - { - switch (MethodType) - { - case MethodType.Unary: - case MethodType.UnaryInPlace: - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - case MethodType.Binary: - case MethodType.Contraction: - return $"{tensorType}<{typeName}>"; - case MethodType.Comparison: - return $"{tensorType}"; - default: - throw new ArgumentException(); - } - } - - public string GetLinearOperationCheck() - { - switch (MethodType) - { - case MethodType.Unary: - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - return $"({ResultName}.IsReversedStride == {Op1Name}.IsReversedStride)"; - case MethodType.Binary: - case MethodType.Comparison: - return $"(({ResultName}.IsReversedStride == {Op1Name}.IsReversedStride) && ({ResultName}.IsReversedStride == {Op2Name}.IsReversedStride))"; - case MethodType.UnaryInPlace: - default: - throw new ArgumentException(); - } - } - - - public string GetElementOperation(string typeName, string access) - { - return GetElementOperation(typeName, access, access, access); - } - - public string GetElementOperation(string typeName, string resultAccess, string leftAccess, string rightAccess) - { - switch (MethodType) - { - case MethodType.Unary: - return $"{ResultName}{resultAccess} = ({typeName}){Operator}{Op1Name}{leftAccess}"; - case MethodType.UnaryInPlace: - return $"{ResultName}{resultAccess}{Operator}"; - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - return $"{ResultName}{resultAccess} = ({typeName})({Op1Name}{leftAccess} {Operator} {Op2Name})"; - case MethodType.Binary: - return $"{ResultName}{resultAccess} = ({typeName})({Op1Name}{leftAccess} {Operator} {Op2Name}{rightAccess})"; - case MethodType.Comparison: - return $"{ResultName}{resultAccess} = {Op1Name}{leftAccess} {Operator} {Op2Name}{rightAccess}"; - default: - throw new ArgumentException(); - - } - } - - public string InitializeResult(string typeName) - { - switch (MethodType) - { - case MethodType.UnaryInPlace: - return $"{Op1Name}.Clone()"; - case MethodType.Unary: - case MethodType.BinaryScalar: - case MethodType.BinaryInt: - case MethodType.Binary: - return $"{Op1Name}.CloneEmpty()"; - case MethodType.Comparison: - return $"{Op1Name}.CloneEmpty()"; - case MethodType.Contraction: - return $"{Op1Name}.CloneEmpty(resultDimensions)"; - default: - throw new ArgumentException(); - } - } - - public bool IsNumeric { get; } - public bool IsBitwise { get; } - } - - - public MethodConfiguration[] methodConfiguration = new [] - { - new MethodConfiguration("Add", MethodType.Binary, "+", isNumeric:true), - new MethodConfiguration("Add", MethodType.BinaryScalar, "+", isNumeric:true), - new MethodConfiguration("UnaryPlus", MethodType.Unary, "+", isNumeric:true), - new MethodConfiguration("Subtract", MethodType.Binary, "-", isNumeric:true), - new MethodConfiguration("Subtract", MethodType.BinaryScalar, "-", isNumeric:true), - new MethodConfiguration("UnaryMinus", MethodType.Unary, "-", isNumeric:true), - new MethodConfiguration("Increment", MethodType.UnaryInPlace, "++", isNumeric:true), - new MethodConfiguration("Decrement", MethodType.UnaryInPlace, "--", isNumeric:true), - new MethodConfiguration("Multiply", MethodType.Binary, "*", isNumeric:true), // element-wise product, not matrix product - new MethodConfiguration("Multiply", MethodType.BinaryScalar, "*", isNumeric:true), - new MethodConfiguration("Divide", MethodType.Binary, "/", isNumeric:true), - new MethodConfiguration("Divide", MethodType.BinaryScalar, "/", isNumeric:true), - new MethodConfiguration("Modulo", MethodType.Binary, "%", isNumeric:true), - new MethodConfiguration("Modulo", MethodType.BinaryScalar, "%", isNumeric:true), - new MethodConfiguration("And", MethodType.Binary, "&", isBitwise: true), - new MethodConfiguration("And", MethodType.BinaryScalar, "&", isBitwise: true), - new MethodConfiguration("Or", MethodType.Binary, "|", isBitwise: true), - new MethodConfiguration("Or", MethodType.BinaryScalar, "|", isBitwise: true), - new MethodConfiguration("Xor", MethodType.Binary, "^", isBitwise: true), - new MethodConfiguration("Xor", MethodType.BinaryScalar, "^", isBitwise: true), - new MethodConfiguration("LeftShift", MethodType.BinaryInt, "<<", isBitwise: true), - new MethodConfiguration("RightShift", MethodType.BinaryInt, ">>", isBitwise: true), - - // Note all of these are element-wise operations not testing the operation on the entire Tensor - new MethodConfiguration("Equals", MethodType.Comparison, "=="), - new MethodConfiguration("NotEquals", MethodType.Comparison, "!="), - new MethodConfiguration("GreaterThanOrEqual", MethodType.Comparison, ">=", isNumeric:true), - new MethodConfiguration("LessThanOrEqual", MethodType.Comparison, "<=", isNumeric:true), - new MethodConfiguration("GreaterThan", MethodType.Comparison, ">", isNumeric:true), - new MethodConfiguration("LessThan", MethodType.Comparison, "<", isNumeric:true), - - new MethodConfiguration("Contract", MethodType.Contraction, isNumeric:true), - }.OrderBy(m => m.MethodName).ToArray(); -#> diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs deleted file mode 100644 index 27c7ba75e4e25..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTests.cs +++ /dev/null @@ -1,2486 +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.Collections; -using System.Collections.Generic; -using System.Linq; -using Xunit; - -namespace System.Numerics.Tensors.Tests -{ - public class TensorTests : TensorTestsBase - { - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructTensorFromArrayRank1(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray(new[] { 0, 1, 2 }); - - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - Assert.Equal(0, tensor[0]); - Assert.Equal(1, tensor[1]); - Assert.Equal(2, tensor[2]); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructTensorFromArrayRank2(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray(new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - Assert.Equal(0, tensor[0, 0]); - Assert.Equal(1, tensor[0, 1]); - Assert.Equal(2, tensor[0, 2]); - Assert.Equal(3, tensor[1, 0]); - Assert.Equal(4, tensor[1, 1]); - Assert.Equal(5, tensor[1, 2]); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructTensorFromArrayRank3(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray(new[, ,] - { - { - {0, 1, 2}, - {3, 4, 5} - }, - { - {6, 7 ,8 }, - {9, 10 ,11 }, - }, - { - {12, 13 ,14 }, - {15, 16 ,17 }, - }, - { - {18, 19 ,20 }, - {21, 22 ,23 }, - } - }); - - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - - Assert.Equal(0, tensor[0, 0, 0]); - Assert.Equal(1, tensor[0, 0, 1]); - Assert.Equal(2, tensor[0, 0, 2]); - Assert.Equal(3, tensor[0, 1, 0]); - Assert.Equal(4, tensor[0, 1, 1]); - Assert.Equal(5, tensor[0, 1, 2]); - - Assert.Equal(6, tensor[1, 0, 0]); - Assert.Equal(7, tensor[1, 0, 1]); - Assert.Equal(8, tensor[1, 0, 2]); - Assert.Equal(9, tensor[1, 1, 0]); - Assert.Equal(10, tensor[1, 1, 1]); - Assert.Equal(11, tensor[1, 1, 2]); - - Assert.Equal(12, tensor[2, 0, 0]); - Assert.Equal(13, tensor[2, 0, 1]); - Assert.Equal(14, tensor[2, 0, 2]); - Assert.Equal(15, tensor[2, 1, 0]); - Assert.Equal(16, tensor[2, 1, 1]); - Assert.Equal(17, tensor[2, 1, 2]); - - Assert.Equal(18, tensor[3, 0, 0]); - Assert.Equal(19, tensor[3, 0, 1]); - Assert.Equal(20, tensor[3, 0, 2]); - Assert.Equal(21, tensor[3, 1, 0]); - Assert.Equal(22, tensor[3, 1, 1]); - Assert.Equal(23, tensor[3, 1, 2]); - } - - [Fact] - public void ConstructDenseTensorFromPointer() - { - using (var nativeMemory = NativeMemoryFromArray(Enumerable.Range(0, 24).ToArray())) - { - var dimensions = new[] { 4, 2, 3 }; - var tensor = new DenseTensor(nativeMemory.Memory, dimensions, false); - - Assert.Equal(0, tensor[0, 0, 0]); - Assert.Equal(1, tensor[0, 0, 1]); - Assert.Equal(2, tensor[0, 0, 2]); - Assert.Equal(3, tensor[0, 1, 0]); - Assert.Equal(4, tensor[0, 1, 1]); - Assert.Equal(5, tensor[0, 1, 2]); - - Assert.Equal(6, tensor[1, 0, 0]); - Assert.Equal(7, tensor[1, 0, 1]); - Assert.Equal(8, tensor[1, 0, 2]); - Assert.Equal(9, tensor[1, 1, 0]); - Assert.Equal(10, tensor[1, 1, 1]); - Assert.Equal(11, tensor[1, 1, 2]); - - Assert.Equal(12, tensor[2, 0, 0]); - Assert.Equal(13, tensor[2, 0, 1]); - Assert.Equal(14, tensor[2, 0, 2]); - Assert.Equal(15, tensor[2, 1, 0]); - Assert.Equal(16, tensor[2, 1, 1]); - Assert.Equal(17, tensor[2, 1, 2]); - - Assert.Equal(18, tensor[3, 0, 0]); - Assert.Equal(19, tensor[3, 0, 1]); - Assert.Equal(20, tensor[3, 0, 2]); - Assert.Equal(21, tensor[3, 1, 0]); - Assert.Equal(22, tensor[3, 1, 1]); - Assert.Equal(23, tensor[3, 1, 2]); - } - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructSparseTensor(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray(new[,] - { - {0, 0, 0, 0}, - {5, 8, 0, 0}, - {0, 0, 3, 0}, - {0, 6, 0, 0} - }); - - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - - - Assert.Equal(0, tensor[0, 0]); - Assert.Equal(0, tensor[0, 1]); - Assert.Equal(0, tensor[0, 2]); - Assert.Equal(0, tensor[0, 3]); - - - Assert.Equal(5, tensor[1, 0]); - Assert.Equal(8, tensor[1, 1]); - Assert.Equal(0, tensor[1, 2]); - Assert.Equal(0, tensor[1, 3]); - - - Assert.Equal(0, tensor[2, 0]); - Assert.Equal(0, tensor[2, 1]); - Assert.Equal(3, tensor[2, 2]); - Assert.Equal(0, tensor[2, 3]); - - - Assert.Equal(0, tensor[3, 0]); - Assert.Equal(6, tensor[3, 1]); - Assert.Equal(0, tensor[3, 2]); - Assert.Equal(0, tensor[3, 3]); - - if (tensorConstructor.TensorType == TensorType.CompressedSparse) - { - var compressedSparseTensor = (CompressedSparseTensor)tensor; - - Assert.Equal(4, compressedSparseTensor.NonZeroCount); - - int[] expectedValues, expectedCompressedCounts, expectedIndices; - - if (compressedSparseTensor.IsReversedStride) - { - // csc - expectedValues = new[] { 5, 8, 6, 3 }; - expectedCompressedCounts = new[] { 0, 1, 3, 4, 4 }; - expectedIndices = new[] { 1, 1, 3, 2 }; - } - else - { - // csr - expectedValues = new[] { 5, 8, 3, 6 }; - expectedCompressedCounts = new[] { 0, 0, 2, 3, 4 }; - expectedIndices = new[] { 0, 1, 2, 1 }; - } - Assert.Equal(expectedValues, compressedSparseTensor.Values.Slice(0, compressedSparseTensor.NonZeroCount).ToArray()); - Assert.Equal(expectedCompressedCounts, compressedSparseTensor.CompressedCounts.ToArray()); - Assert.Equal(expectedIndices, compressedSparseTensor.Indices.Slice(0, compressedSparseTensor.NonZeroCount).ToArray()); - } - } - - [Theory()] - [InlineData(false)] - [InlineData(true)] - public void ConstructCompressedSparseTensorFromPointers(bool isReversedStride) - { - int[] values, compressedCounts, indices; - if (isReversedStride) - { - // csc - values = new[] { 5, 8, 6, 3 }; - compressedCounts = new[] { 0, 1, 3, 4, 4 }; - indices = new[] { 1, 1, 3, 2 }; - } - else - { - // csr - values = new[] { 5, 8, 3, 6 }; - compressedCounts = new[] { 0, 0, 2, 3, 4 }; - indices = new[] { 0, 1, 2, 1 }; - } - int[] dimensions = new[] { 4, 4 }; - - using (var valuesMemory = NativeMemoryFromArray(values)) - using (var compressedCountsMemory = NativeMemoryFromArray(compressedCounts)) - using (var indicesMemory = NativeMemoryFromArray(indices)) - { - var tensor = new CompressedSparseTensor(valuesMemory.Memory, - compressedCountsMemory.Memory, - indicesMemory.Memory, - values.Length, - dimensions, - isReversedStride); - - Assert.Equal(0, tensor[0, 0]); - Assert.Equal(0, tensor[0, 1]); - Assert.Equal(0, tensor[0, 2]); - Assert.Equal(0, tensor[0, 3]); - - - Assert.Equal(5, tensor[1, 0]); - Assert.Equal(8, tensor[1, 1]); - Assert.Equal(0, tensor[1, 2]); - Assert.Equal(0, tensor[1, 3]); - - - Assert.Equal(0, tensor[2, 0]); - Assert.Equal(0, tensor[2, 1]); - Assert.Equal(3, tensor[2, 2]); - Assert.Equal(0, tensor[2, 3]); - - - Assert.Equal(0, tensor[3, 0]); - Assert.Equal(6, tensor[3, 1]); - Assert.Equal(0, tensor[3, 2]); - Assert.Equal(0, tensor[3, 3]); - } - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructFromDimensions(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromDimensions(new[] { 2, 3, 4 }); - Assert.Equal(3, tensor.Rank); - Assert.Equal(3, tensor.Dimensions.Length); - Assert.Equal(2, tensor.Dimensions[0]); - Assert.Equal(3, tensor.Dimensions[1]); - Assert.Equal(4, tensor.Dimensions[2]); - Assert.Equal(24, tensor.Length); - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - - //Assert.Throws("dimensions", () => tensorConstructor.CreateFromDimensions(dimensions: null)); - Assert.Throws("dimensions", () => tensorConstructor.CreateFromDimensions(dimensions: new int[0])); - - Assert.Throws("dimensions", () => tensorConstructor.CreateFromDimensions(dimensions: new[] { 1, 0 })); - Assert.Throws("dimensions", () => tensorConstructor.CreateFromDimensions(dimensions: new[] { 1, -1 })); - - // ensure dimensions are immutable - var dimensions = new[] { 1, 2, 3 }; - tensor = tensorConstructor.CreateFromDimensions(dimensions: dimensions); - dimensions[0] = dimensions[1] = dimensions[2] = 0; - Assert.Equal(1, tensor.Dimensions[0]); - Assert.Equal(2, tensor.Dimensions[1]); - Assert.Equal(3, tensor.Dimensions[2]); - } - - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNonZeroLowerBoundArraySupported))] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ConstructTensorFromArrayRank3WithLowerBounds(TensorConstructor tensorConstructor) - { - var dimensions = new[] { 2, 3, 4 }; - var lowerBounds = new[] { 0, 5, 200 }; - var arrayWithLowerBounds = Array.CreateInstance(typeof(int), dimensions, lowerBounds); - - int value = 0; - for (int x = lowerBounds[0]; x < lowerBounds[0] + dimensions[0]; x++) - { - for (int y = lowerBounds[1]; y < lowerBounds[1] + dimensions[1]; y++) - { - for (int z = lowerBounds[2]; z < lowerBounds[2] + dimensions[2]; z++) - { - arrayWithLowerBounds.SetValue(value++, x, y, z); - } - } - } - - var tensor = tensorConstructor.CreateFromArray(arrayWithLowerBounds); - - var expected = tensorConstructor.CreateFromArray(new[, ,] - { - { - { 0, 1, 2, 3 }, - { 4, 5, 6, 7 }, - { 8, 9, 10, 11 } - }, - { - { 12, 13, 14, 15 }, - { 16, 17, 18, 19 }, - { 20, 21, 22, 23 } - } - } - ); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(expected, tensor)); - Assert.Equal(tensorConstructor.IsReversedStride, tensor.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void StructurallyEqualTensor(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var arr = new[, ,] - { - { - {0, 1, 2}, - {3, 4, 5} - }, - { - {6, 7 ,8 }, - {9, 10 ,11 }, - }, - { - {12, 13 ,14 }, - {15, 16 ,17 }, - }, - { - {18, 19 ,20 }, - {21, 22 ,23 }, - } - }; - var tensor = leftConstructor.CreateFromArray(arr); - var tensor2 = rightConstructor.CreateFromArray(arr); - - Assert.Equal(0, StructuralComparisons.StructuralComparer.Compare(tensor, tensor2)); - Assert.Equal(0, StructuralComparisons.StructuralComparer.Compare(tensor2, tensor)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, tensor2)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor2, tensor)); - // Issue: should Tensors with different layout be structurally equal? - if (leftConstructor.IsReversedStride == leftConstructor.IsReversedStride) - { - Assert.Equal(StructuralComparisons.StructuralEqualityComparer.GetHashCode(tensor), StructuralComparisons.StructuralEqualityComparer.GetHashCode(tensor2)); - } - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void StructurallyEqualArray(TensorConstructor tensorConstructor) - { - var arr = new[, ,] - { - { - {0, 1, 2}, - {3, 4, 5} - }, - { - {6, 7 ,8 }, - {9, 10 ,11 }, - }, - { - {12, 13 ,14 }, - {15, 16 ,17 }, - }, - { - {18, 19 ,20 }, - {21, 22 ,23 }, - } - }; - var tensor = tensorConstructor.CreateFromArray(arr); - - Assert.Equal(0, StructuralComparisons.StructuralComparer.Compare(tensor, arr)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, arr)); - - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetDiagonalSquare(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var diag = tensor.GetDiagonal(); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 1, 3, 5 })); - diag = tensor.GetDiagonal(1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 2, 9 })); - diag = tensor.GetDiagonal(2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 4 })); - Assert.Throws("offset", () => tensor.GetDiagonal(3)); - - diag = tensor.GetDiagonal(-1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 8, 7 })); - diag = tensor.GetDiagonal(-2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 1 })); - Assert.Throws("offset", () => tensor.GetDiagonal(-3)); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetDiagonalRectangle(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var diag = tensor.GetDiagonal(); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 1, 3, 5 })); - diag = tensor.GetDiagonal(1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 2, 9, 2 })); - diag = tensor.GetDiagonal(2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 4, 2, 9 })); - diag = tensor.GetDiagonal(3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 3, 6 })); - diag = tensor.GetDiagonal(4); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 7 })); - Assert.Throws("offset", () => tensor.GetDiagonal(5)); - - diag = tensor.GetDiagonal(-1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 8, 7 })); - diag = tensor.GetDiagonal(-2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, new[] { 1 })); - Assert.Throws("offset", () => tensor.GetDiagonal(-3)); - Assert.Throws("offset", () => tensor.GetDiagonal(-4)); - Assert.Throws("offset", () => tensor.GetDiagonal(-5)); - } - - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetDiagonalCube(TensorConstructor tensorConstructor) - { - var arr = new[, ,] - { - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }, - { - { 4, 5, 7 }, - { 1, 6, 2 }, - { 3, 0, 8 }, - }, - { - { 5, 6, 1 }, - { 2, 2, 3 }, - { 4, 9, 4 }, - }, - - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var diag = tensor.GetDiagonal(); - var expected = new[,] - { - { 1, 2, 4 }, - { 1, 6, 2 }, - { 4, 9, 4 } - }; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(diag, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, diag.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetTriangleSquare(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetTriangle(0); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - - var expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 0, 0 }, - { 8, 3, 0 }, - { 1, 7, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 0 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(200); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(-1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0 }, - { 8, 0, 0 }, - { 1, 7, 0 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(-2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1, 0, 0 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - }); - tri = tensor.GetTriangle(-3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - // same as -3, should it be an exception? - tri = tensor.GetTriangle(-4); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(-300); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetTriangleRectangle(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetTriangle(0); - var expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 0, 0, 0, 0 }, - { 8, 3, 0, 0, 0 }, - { 1, 7, 5, 0, 0 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - - tri = tensor.GetTriangle(1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 0, 0, 0 }, - { 8, 3, 9, 0, 0 }, - { 1, 7, 5, 2, 0 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 0, 0 }, - { 8, 3, 9, 2, 0 }, - { 1, 7, 5, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(3); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 3, 0 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(4); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - // same as 4, should it be an exception? - tri = tensor.GetTriangle(5); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(1000); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(-1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 0, 0 }, - { 8, 0, 0, 0, 0 }, - { 1, 7, 0, 0, 0 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - { 1, 0, 0, 0, 0 } - }); - tri = tensor.GetTriangle(-2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 } - }); - tri = tensor.GetTriangle(-3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetTriangle(-4); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(-5); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetTriangle(-100); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetTriangleCube(TensorConstructor tensorConstructor) - { - var arr = new[, ,] - { - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }, - { - { 4, 5, 7 }, - { 1, 6, 2 }, - { 3, 0, 8 }, - }, - { - { 5, 6, 1 }, - { 2, 2, 3 }, - { 4, 9, 4 }, - }, - - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetTriangle(0); - var expected = tensorConstructor.CreateFromArray(new[, ,] - { - { - { 1, 2, 4 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - }, - { - { 4, 5, 7 }, - { 1, 6, 2 }, - { 0, 0, 0 }, - }, - { - { 5, 6, 1 }, - { 2, 2, 3 }, - { 4, 9, 4 }, - }, - - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetUpperTriangleSquare(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetUpperTriangle(0); - - var expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4 }, - { 0, 3, 9 }, - { 0, 0, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - - tri = tensor.GetUpperTriangle(1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 2, 4 }, - { 0, 0, 9 }, - { 0, 0, 0 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 4 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(3); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(4); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(42); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(-1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 0, 7, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(-2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(-3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(-300); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetUpperTriangleRectangle(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetUpperTriangle(0); - var expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 3, 7 }, - { 0, 3, 9, 2, 6 }, - { 0, 0, 5, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - tri = tensor.GetUpperTriangle(1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 2, 4, 3, 7 }, - { 0, 0, 9, 2, 6 }, - { 0, 0, 0, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(2); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 4, 3, 7 }, - { 0, 0, 0, 2, 6 }, - { 0, 0, 0, 0, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(3); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 3, 7 }, - { 0, 0, 0, 0, 6 }, - { 0, 0, 0, 0, 0 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(4); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 0, 7 }, - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - expected = tensorConstructor.CreateFromArray(new[,] - { - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 } - }); - tri = tensor.GetUpperTriangle(5); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(6); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(1000); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(-1); - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 0, 7, 5, 2, 9 } - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - expected = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 4, 3, 7 }, - { 8, 3, 9, 2, 6 }, - { 1, 7, 5, 2, 9 } - }); - tri = tensor.GetUpperTriangle(-2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - - tri = tensor.GetUpperTriangle(-3); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(-4); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - tri = tensor.GetUpperTriangle(-100); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetUpperTriangleCube(TensorConstructor tensorConstructor) - { - var arr = new[, ,] - { - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }, - { - { 4, 5, 7 }, - { 1, 6, 2 }, - { 3, 0, 8 }, - }, - { - { 5, 6, 1 }, - { 2, 2, 3 }, - { 4, 9, 4 }, - }, - - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var tri = tensor.GetUpperTriangle(0); - var expected = tensorConstructor.CreateFromArray(new[, ,] - { - { - { 1, 2, 4 }, - { 8, 3, 9 }, - { 1, 7, 5 }, - }, - { - { 0, 0, 0 }, - { 1, 6, 2 }, - { 3, 0, 8 }, - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 4, 9, 4 }, - }, - - }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tri, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, tri.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void Reshape(TensorConstructor tensorConstructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = tensorConstructor.CreateFromArray(arr); - var actual = tensor.Reshape(new[] { 3, 2 }); - - var expected = tensorConstructor.IsReversedStride ? - new[,] - { - { 1, 5 }, - { 4, 3 }, - { 2, 6 } - } : - new[,] - { - { 1, 2 }, - { 3, 4 }, - { 5, 6 } - }; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Fact] - public void Identity() - { - var actual = Tensor.CreateIdentity(3); - - var expected = new[,] - { - {1.0, 0, 0 }, - {0, 1.0, 0 }, - {0, 0, 1.0 } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void CreateWithDiagonal(TensorConstructor tensorConstructor) - { - var diagonal = tensorConstructor.CreateFromArray(new[] { 1, 2, 3, 4, 5 }); - var actual = Tensor.CreateFromDiagonal(diagonal); - - var expected = new[,] - { - {1, 0, 0, 0, 0 }, - {0, 2, 0, 0, 0 }, - {0, 0, 3, 0, 0 }, - {0, 0, 0, 4, 0 }, - {0, 0, 0, 0, 5 } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void CreateWithDiagonal3D(TensorConstructor tensorConstructor) - { - var diagonal = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 3, 4, 5 }, - { 1, 2, 3, 4, 5 }, - { 1, 2, 3, 4, 5 } - }); - var actual = Tensor.CreateFromDiagonal(diagonal); - var expected = new[, ,] - { - { - {1, 2, 3, 4, 5 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 } - }, - { - {0, 0, 0, 0, 0 }, - {1, 2, 3, 4, 5 }, - {0, 0, 0, 0, 0 } - }, - { - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {1, 2, 3, 4, 5 } - } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void CreateWithDiagonalAndOffset(TensorConstructor tensorConstructor) - { - var diagonal = tensorConstructor.CreateFromArray(new[] { 1, 2, 3, 4 }); - var actual = Tensor.CreateFromDiagonal(diagonal, 1); - - var expected = new[,] - { - {0, 1, 0, 0, 0 }, - {0, 0, 2, 0, 0 }, - {0, 0, 0, 3, 0 }, - {0, 0, 0, 0, 4 }, - {0, 0, 0, 0, 0 } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[] { 1, 2, 3, 4 }); - actual = Tensor.CreateFromDiagonal(diagonal, -1); - - expected = new[,] - { - {0, 0, 0, 0, 0 }, - {1, 0, 0, 0, 0 }, - {0, 2, 0, 0, 0 }, - {0, 0, 3, 0, 0 }, - {0, 0, 0, 4, 0 } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[] { 1 }); - actual = Tensor.CreateFromDiagonal(diagonal, -4); - expected = new[,] - { - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {1, 0, 0, 0, 0 } - }; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[] { 1 }); - actual = Tensor.CreateFromDiagonal(diagonal, 4); - expected = new[,] - { - {0, 0, 0, 0, 1 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 }, - {0, 0, 0, 0, 0 } - }; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void CreateWithDiagonalAndOffset3D(TensorConstructor tensorConstructor) - { - var diagonal = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 3 }, - { 1, 2, 3 }, - { 1, 2, 3 } - }); - var actual = Tensor.CreateFromDiagonal(diagonal, 1); - - var expected = new[, ,] - { - { - { 0, 0, 0 }, - { 1, 2, 3 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1, 2, 3 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1, 2, 3 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 3 }, - { 1, 2, 3 }, - { 1, 2, 3 } - }); - actual = Tensor.CreateFromDiagonal(diagonal, -1); - - expected = new[, ,] - { - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 1, 2, 3 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 1, 2, 3 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1, 2, 3 }, - { 0, 0, 0 } - } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 3 } - }); - actual = Tensor.CreateFromDiagonal(diagonal, 3); - - expected = new[, ,] - { - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1, 2, 3 }, - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - diagonal = tensorConstructor.CreateFromArray(new[,] - { - { 1, 2, 3 } - }); - actual = Tensor.CreateFromDiagonal(diagonal, -3); - - expected = new[, ,] - { - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - }, - { - { 1, 2, 3 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 } - } - }; - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Add(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var right = rightConstructor.CreateFromArray( - new[,] - { - { 6, 7 ,8 }, - { 9, 10 ,11 }, - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - { 6, 8, 10 }, - { 12, 14, 16 }, - }); - - var actual = TensorOperations.Add(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void AddScalar(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 }, - }); - - var actual = TensorOperations.Add(tensor, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void UnaryPlus(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensor; - - var actual = TensorOperations.UnaryPlus(tensor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.False(ReferenceEquals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Subtract(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var right = rightConstructor.CreateFromArray( - new[,] - { - { 6, 7 ,8 }, - { 9, 10 ,11 }, - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - { -6, -6, -6 }, - { -6, -6, -6}, - }); - - var actual = TensorOperations.Subtract(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void SubtractScalar(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var expected = tensorConstructor.CreateFromArray( - new[,] - { - { -1, 0, 1 }, - { 2, 3, 4 }, - }); - - var actual = TensorOperations.Subtract(tensor, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void UnaryMinus(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, -1, -2}, - {-3, -4, -5} - }); - - var actual = TensorOperations.UnaryMinus(tensor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.False(ReferenceEquals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void PrefixIncrement(TensorConstructor tensorConstructor) - { - Tensor tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expectedResult = tensorConstructor.CreateFromArray( - new[,] - { - {1, 2, 3}, - {4, 5, 6} - }); - - var expectedTensor = expectedResult; - - tensor = TensorOperations.Increment(tensor); - var actual = tensor; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expectedResult)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, expectedTensor)); - Assert.True(ReferenceEquals(tensor, actual)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void PostfixIncrement(TensorConstructor tensorConstructor) - { - Tensor tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - // returns original value - var expectedResult = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - // increments operand - var expectedTensor = tensorConstructor.CreateFromArray( - new[,] - { - {1, 2, 3}, - {4, 5, 6} - }); - - var actual = tensor; - tensor = TensorOperations.Increment(tensor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expectedResult)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, expectedTensor)); - Assert.False(ReferenceEquals(tensor, actual)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void PrefixDecrement(TensorConstructor tensorConstructor) - { - Tensor tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expectedResult = tensorConstructor.CreateFromArray( - new[,] - { - {-1, 0, 1}, - {2, 3, 4} - }); - - var expectedTensor = expectedResult; - - tensor = TensorOperations.Decrement(tensor); - var actual = tensor; - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expectedResult)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, expectedTensor)); - Assert.True(ReferenceEquals(tensor, actual)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void PostfixDecrement(TensorConstructor tensorConstructor) - { - Tensor tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - // returns original value - var expectedResult = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - // decrements operand - var expectedTensor = tensorConstructor.CreateFromArray( - new[,] - { - {-1, 0, 1}, - {2, 3, 4} - }); - - var actual = tensor; - tensor = TensorOperations.Decrement(tensor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expectedResult)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(tensor, expectedTensor)); - Assert.False(ReferenceEquals(tensor, actual)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Multiply(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var right = rightConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 4}, - {9, 16, 25} - }); - - var actual = TensorOperations.Multiply(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void MultiplyScalar(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 2, 4}, - {6, 8, 10} - }); - - var actual = TensorOperations.Multiply(tensor, 2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Divide(TensorConstructor dividendConstructor, TensorConstructor divisorConstructor) - { - var dividend = dividendConstructor.CreateFromArray( - new[,] - { - {0, 1, 4}, - {9, 16, 25} - }); - - var divisor = divisorConstructor.CreateFromArray( - new[,] - { - {1, 1, 2}, - {3, 4, 5} - }); - - var expected = divisorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var actual = TensorOperations.Divide(dividend, divisor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(dividendConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void DivideScalar(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 2, 4}, - {6, 8, 10} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var actual = TensorOperations.Divide(tensor, 2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Modulo(TensorConstructor dividendConstructor, TensorConstructor divisorConstructor) - { - var dividend = dividendConstructor.CreateFromArray( - new[,] - { - {0, 3, 8}, - {11, 14, 17} - }); - - var divisor = divisorConstructor.CreateFromArray( - new[,] - { - {1, 2, 3}, - {4, 5, 6} - }); - - var expected = dividendConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var actual = TensorOperations.Modulo(dividend, divisor); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(dividendConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void ModuloScalar(TensorConstructor tensorConstructor) - { - var tensor = tensorConstructor.CreateFromArray( - new[,] - { - {0, 3, 4}, - {7, 8, 9} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 0}, - {1, 0, 1} - }); - - var actual = TensorOperations.Modulo(tensor, 2); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void And(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 3}, - {7, 15, 31} - }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - {1, 1, 3}, - {2, 4, 8} - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 3}, - {2, 4, 8} - }); - - var actual = TensorOperations.And(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void AndScalar(TensorConstructor tensorConstructor) - { - var left = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 3}, - {5, 15, 31} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 0, 0}, - {4, 4, 20} - }); - - var actual = TensorOperations.And(left, 20); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Or(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 3}, - {7, 14, 31} - }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - {1, 2, 4}, - {2, 4, 8} - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {1, 3, 7}, - {7, 14, 31} - }); - - var actual = TensorOperations.Or(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void OrScalar(TensorConstructor tensorConstructor) - { - var left = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {1, 1, 3}, - {3, 5, 5} - }); - - var actual = TensorOperations.Or(left, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void Xor(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 3}, - {7, 14, 31} - }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - {1, 2, 4}, - {2, 4, 8} - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {1, 3, 7}, - {5, 10, 23} - }); - - var actual = TensorOperations.Xor(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void XorScalar(TensorConstructor tensorConstructor) - { - var left = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {1, 0, 3}, - {2, 5, 4} - }); - - var actual = TensorOperations.Xor(left, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void LeftShift(TensorConstructor tensorConstructor) - { - var left = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 2, 4}, - {6, 8, 10} - }); - - var actual = TensorOperations.LeftShift(left, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetSingleTensorConstructors))] - public void RightShift(TensorConstructor tensorConstructor) - { - var left = tensorConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var expected = tensorConstructor.CreateFromArray( - new[,] - { - {0, 0, 1}, - {1, 2, 2} - }); - - var actual = TensorOperations.RightShift(left, 1); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(tensorConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void ElementWiseEquals(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var right = rightConstructor.CreateFromArray( - new[,] - { - {0, 1, -2}, - {2, 3, 5} - }); - - var expected = new[,] - { - {true, true, false }, - {false, false, true} - }.ToTensor(); - - var actual = TensorOperations.Equals(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory()] - [MemberData(nameof(GetDualTensorConstructors))] - public void ElementWiseNotEquals(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - var right = rightConstructor.CreateFromArray( - new[,] - { - {0, 1, -2}, - {2, 3, 5} - }); - - var expected = new[,] - { - {false, false, true}, - {true, true, false} - }.ToTensor(); - - var actual = TensorOperations.NotEquals(left, right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.Equal(leftConstructor.IsReversedStride, actual.IsReversedStride); - } - - [Theory] - [MemberData(nameof(GetDualTensorConstructors))] - public void MatrixMultiply(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {0, 1, 2}, - {3, 4, 5} - }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - {0, 1, 2, 3, 4}, - {5, 6, 7, 8, 9}, - {10, 11, 12, 13, 14} - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {0*0 + 1*5 + 2*10, 0*1 + 1*6 + 2*11, 0*2 + 1*7 + 2*12, 0*3 + 1*8 + 2*13, 0*4 + 1*9 + 2*14}, - {3*0 + 4*5 + 5*10, 3*1 + 4*6 + 5*11, 3*2 + 4*7 + 5*12, 3*3 + 4*8 + 5*13, 3*4 + 4*9 + 5*14} - }); - - var actual = left.MatrixMultiply(right); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - - [Theory] - [MemberData(nameof(GetDualTensorConstructors))] - public void Contract(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[, ,] - { - { - {0, 1}, - {2, 3} - }, - { - {4, 5}, - {6, 7} - }, - { - {8, 9}, - {10, 11} - } - }); - - var right = rightConstructor.CreateFromArray( - new[, ,] - { - { - {0, 1}, - {2, 3}, - {4, 5} - }, - { - {6, 7}, - {8, 9}, - {10, 11} - }, - { - {12, 13}, - {14, 15}, - {16, 17} - }, - { - {18, 19}, - {20, 21}, - {22, 23} - } - }); - - // contract a 3*2*2 with a 4*3*2 tensor, summing on (3*2)*2 and 4*(3*2) to produce a 2*4 tensor - var expected = leftConstructor.CreateFromArray( - new[,] - { - {110, 290, 470, 650}, - {125, 341, 557, 773}, - }); - var actual = TensorOperations.Contract(left, right, new[] { 0, 1 }, new[] { 1, 2 }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - // contract a 3*2*2 with a 4*3*2 tensor, summing on (3)*2*(2) and 4*(3*2) to produce a 2*4 tensor - expected = leftConstructor.CreateFromArray( - new[,] - { - {101, 263, 425, 587}, - {131, 365, 599, 833}, - }); - actual = TensorOperations.Contract(left, right, new[] { 0, 2 }, new[] { 1, 2 }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - - [Theory] - [MemberData(nameof(GetDualTensorConstructors))] - public void ContractWithSingleLengthDimension(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[,] - { - {1, 2, 3}, - {4, 5, 6}, - }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - { 1, 2 }, - { 3, 4 }, - { 5, 6 } - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - { 22, 28 }, - { 49, 64 } - }); - - // contract a 2*3 with a 3*2 tensor, summing on 2*(3) and (3)*2 to produce a 2*2 tensor - var actual = TensorOperations.Contract(left, right, new[] { 1 }, new[] { 0 }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - - // contract a 1*2*3*1 with a 3*2 tensor, summing on 1*2*(3)*1 and (3)*2 to produce a 1*2*1*2 tensor - var reshapedLeft = left.Reshape(new int[] { 1, 2, 3, 1 }); - var reshapedExpected = expected.Reshape(new int[] { 1, 2, 1, 2 }); - actual = TensorOperations.Contract(reshapedLeft, right, new[] { 2 }, new[] { 0 }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, reshapedExpected)); - - } - - [Theory] - [MemberData(nameof(GetDualTensorConstructors))] - public void ContractMismatchedDimensions(TensorConstructor leftConstructor, TensorConstructor rightConstructor) - { - var left = leftConstructor.CreateFromArray( - new[] { 0, 1, 2, 3 }); - - var right = rightConstructor.CreateFromArray( - new[,] - { - { 0 }, - { 1 }, - { 2 } - }); - - var expected = leftConstructor.CreateFromArray( - new[,] - { - {0,0,0}, - {0,1,2}, - {0,2,4}, - {0,3,6}, - }); - - Assert.Throws(() => TensorOperations.Contract(left, right, new int[] { }, new[] { 1 })); - - // reshape to include dimension of length 1. - var leftReshaped = left.Reshape(new[] { 1, (int)left.Length }); - - var actual = TensorOperations.Contract(leftReshaped, right, new[] { 0 }, new[] { 1 }); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void GetArrayString(TensorConstructor constructor) - { - var tensor = constructor.CreateFromArray( - new[, ,] - { - { - {0, 1}, - {2, 3}, - {4, 5} - }, - { - {6, 7}, - {8, 9}, - {10, 11} - }, - { - {12, 13}, - {14, 15}, - {16, 17} - }, - { - {18, 19}, - {20, 21}, - {22, 23} - } - }); - - var expected = -@"{ - { - {0,1}, - {2,3}, - {4,5} - }, - { - {6,7}, - {8,9}, - {10,11} - }, - { - {12,13}, - {14,15}, - {16,17} - }, - { - {18,19}, - {20,21}, - {22,23} - } -}"; - - Assert.Equal(expected, tensor.GetArrayString(), ignoreLineEndingDifferences: !LineEndingsHelper.IsNewLineConsistent); - - var expectedNoSpace = expected.Replace(LineEndingsHelper.CompiledNewline, "").Replace(" ", ""); - Assert.Equal(expectedNoSpace, tensor.GetArrayString(false)); - } - - [Theory] - [MemberData(nameof(GetTensorAndResultConstructor))] - public void ToOtherTensor(TensorConstructor sourceConstructor, TensorConstructor resultConstructor) - { - var array = new[, ,] - { - { - {0, 1, 0, 0 }, - {0, 0, 0, 9 }, - {2, 0, 5, 0 } - }, - { - {3, 0, 0, 6 }, - {0, 0, 0, 0 }, - {0, 0, 4, 0 } - }, - { - {0, 2, 0, 0 }, - {8, 0, 0, 0 }, - {0, 0, 12, 0 } - }, - { - {5, 5, 5, 0 }, - {0, 0, 0, 15 }, - {0, 0, 42, 0 } - }, - { - {1, 0, 0, 4 }, - {0, 2, 0, 0 }, - {0, 0, 3, 0 } - } - }; - - var source = sourceConstructor.CreateFromArray(array); - - Tensor expected = resultConstructor.CreateFromArray(array); - - Tensor actual; - - switch (resultConstructor.TensorType) - { - case TensorType.Dense: - actual = source.ToDenseTensor(); - break; - case TensorType.Sparse: - var actualSparse = source.ToSparseTensor(); - actual = actualSparse; - var expectedSparse = expected as SparseTensor; - Assert.Equal(expectedSparse.NonZeroCount, actualSparse.NonZeroCount); - break; - case TensorType.CompressedSparse: - var actualCompressedSparse = source.ToCompressedSparseTensor(); - actual = actualCompressedSparse; - var expectedCompressedSparse = expected as CompressedSparseTensor; - Assert.Equal(expectedCompressedSparse.NonZeroCount, actualCompressedSparse.NonZeroCount); - if (sourceConstructor.TensorType != TensorType.Dense) - { - // expect packed values when going from sparse -> sparse - Assert.Equal(actualCompressedSparse.NonZeroCount, actualCompressedSparse.Values.Length); - } - break; - default: - throw new ArgumentException(nameof(resultConstructor.TensorType)); - } - - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, expected)); - Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(actual, source)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void TestICollectionMembers(TensorConstructor constructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = constructor.CreateFromArray(arr); - ICollection tensorCollection = tensor; - - Assert.Equal(6, tensorCollection.Count); - - Assert.False(tensorCollection.IsSynchronized); - - Assert.True(ReferenceEquals(tensorCollection, tensorCollection.SyncRoot)); - - var actual = Array.CreateInstance(typeof(int), tensor.Length); - tensorCollection.CopyTo(actual, 0); - var expected = constructor.IsReversedStride ? - new[] { 1, 4, 2, 5, 3, 6 } : - new[] { 1, 2, 3, 4, 5, 6 }; - Assert.Equal(expected, actual); - - actual = Array.CreateInstance(typeof(int), tensor.Length + 2); - tensorCollection.CopyTo(actual, 2); - expected = constructor.IsReversedStride ? - new[] { 0, 0, 1, 4, 2, 5, 3, 6 } : - new[] { 0, 0, 1, 2, 3, 4, 5, 6 }; - Assert.Equal(expected, actual); - - Assert.Throws(() => tensorCollection.CopyTo(null, 0)); - Assert.Throws(() => tensorCollection.CopyTo(new int[3, 4], 0)); - Assert.Throws(() => tensorCollection.CopyTo(new int[5], 0)); - Assert.Throws(() => tensorCollection.CopyTo(new int[6], 1)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void TestIListMembers(TensorConstructor constructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = constructor.CreateFromArray(arr); - IList tensorList = tensor; - - int expectedIndexValue = constructor.IsReversedStride ? 4 : 2; - Assert.Equal(expectedIndexValue, tensorList[1]); - - tensorList[1] = 7; - Assert.Equal(7, tensorList[1]); - var expected = constructor.IsReversedStride ? - new[] { 1, 7, 2, 5, 3, 6 } : - new[] { 1, 7, 3, 4, 5, 6 }; - Assert.Equal(expected, tensor); - - Assert.True(tensorList.IsFixedSize); - Assert.False(tensorList.IsReadOnly); - - Assert.Throws(() => (tensorList).Add(8)); - - Assert.True(tensorList.Contains(5)); - Assert.True(tensorList.Contains(6)); - Assert.False(tensorList.Contains(0)); - Assert.False(tensorList.Contains(42)); - Assert.False(tensorList.Contains("foo")); - - Assert.Equal(constructor.IsReversedStride ? 3 : 4, tensorList.IndexOf(5)); - Assert.Equal(5, tensorList.IndexOf(6)); - Assert.Equal(-1, tensorList.IndexOf(0)); - Assert.Equal(-1, tensorList.IndexOf(42)); - - Assert.Throws(() => (tensorList).Insert(2, 5)); - Assert.Throws(() => (tensorList).Remove(1)); - Assert.Throws(() => (tensorList).RemoveAt(0)); - - tensorList.Clear(); - Assert.Equal(new[] { 0, 0, 0, 0, 0, 0 }, tensor); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void TestICollectionTMembers(TensorConstructor constructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = constructor.CreateFromArray(arr); - ICollection tensorCollection = tensor; - - Assert.Equal(6, tensorCollection.Count); - Assert.False(tensorCollection.IsReadOnly); - - Assert.Throws(() => tensorCollection.Add(8)); - Assert.Throws(() => tensorCollection.Remove(1)); - - Assert.True(tensorCollection.Contains(5)); - Assert.True(tensorCollection.Contains(6)); - Assert.False(tensorCollection.Contains(0)); - Assert.False(tensorCollection.Contains(42)); - - var actual = new int[tensor.Length]; - tensorCollection.CopyTo(actual, 0); - var expected = constructor.IsReversedStride ? - new[] { 1, 4, 2, 5, 3, 6 } : - new[] { 1, 2, 3, 4, 5, 6 }; - Assert.Equal(expected, actual); - - actual = new int[tensor.Length + 2]; - tensorCollection.CopyTo(actual, 2); - expected = constructor.IsReversedStride ? - new[] { 0, 0, 1, 4, 2, 5, 3, 6 } : - new[] { 0, 0, 1, 2, 3, 4, 5, 6 }; - Assert.Equal(expected, actual); - - Assert.Throws(() => tensorCollection.CopyTo(null, 0)); - Assert.Throws(() => tensorCollection.CopyTo(new int[5], 0)); - Assert.Throws(() => tensorCollection.CopyTo(new int[6], 1)); - - tensorCollection.Clear(); - Assert.Equal(new[] { 0, 0, 0, 0, 0, 0 }, tensor); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void TestIListTMembers(TensorConstructor constructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = constructor.CreateFromArray(arr); - IList tensorList = tensor; - - int expectedIndexValue = constructor.IsReversedStride ? 4 : 2; - Assert.Equal(expectedIndexValue, tensorList[1]); - - tensorList[1] = 7; - Assert.Equal(7, tensorList[1]); - var expected = constructor.IsReversedStride ? - new[] { 1, 7, 2, 5, 3, 6 } : - new[] { 1, 7, 3, 4, 5, 6 }; - Assert.Equal(expected, tensor); - - Assert.Equal(constructor.IsReversedStride ? 3 : 4, tensorList.IndexOf(5)); - Assert.Equal(5, tensorList.IndexOf(6)); - Assert.Equal(-1, tensorList.IndexOf(0)); - Assert.Equal(-1, tensorList.IndexOf(42)); - - Assert.Throws(() => (tensorList).Insert(2, 5)); - Assert.Throws(() => (tensorList).RemoveAt(0)); - } - - [Theory] - [MemberData(nameof(GetSingleTensorConstructors))] - public void TestIReadOnlyTMembers(TensorConstructor constructor) - { - var arr = new[,] - { - { 1, 2, 3 }, - { 4, 5, 6 } - }; - - var tensor = constructor.CreateFromArray(arr); - - IReadOnlyCollection tensorCollection = tensor; - Assert.Equal(6, tensorCollection.Count); - - IReadOnlyList tensorList = tensor; - int expectedIndexValue = constructor.IsReversedStride ? 4 : 2; - Assert.Equal(expectedIndexValue, tensorList[1]); - } - - [Theory] - [MemberData(nameof(GetConstructedTensors))] - public void TestGetEnumerator(Tensor tensor) - { - static IEnumerable GetExpected(Tensor tensor) - { - for (int index = 0; index < tensor.Length; ++index) - yield return tensor.GetValue(index); - } - - Assert.Equal(GetExpected(tensor), tensor); - } - - [Theory] - [MemberData(nameof(GetConstructedTensors))] - public void TestEnumeratorReset(Tensor tensor) - { - static long AdvanceEnumerator(ref Tensor.Enumerator enumerator, long maxCount) - { - long count = 0; - while (count < maxCount && enumerator.MoveNext()) - count++; - - return count; - } - - static void TestStepCountIfInRange(Tensor tensor, long stepCount) - { - if (stepCount < 0 || stepCount > tensor.Length) - return; - - var enumerator = tensor.GetEnumerator(); - long actualStepCount = AdvanceEnumerator(ref enumerator, stepCount); - - Assert.Equal(stepCount, actualStepCount); - - enumerator.Reset(); - - var itemsPostReset = new List(); - while (enumerator.MoveNext()) - itemsPostReset.Add(enumerator.Current); - - Assert.Equal(tensor, itemsPostReset); - } - - TestStepCountIfInRange(tensor, 1); - TestStepCountIfInRange(tensor, tensor.Length - 1); - TestStepCountIfInRange(tensor, tensor.Length / 4); - TestStepCountIfInRange(tensor, tensor.Length - tensor.Length / 4); - TestStepCountIfInRange(tensor, tensor.Length / 2); - TestStepCountIfInRange(tensor, tensor.Length); - } - - [Theory] - [MemberData(nameof(GetConstructedTensors))] - public void TestEnumeratorDispose_DoesNotThrow(Tensor tensor) - { - var enumerator = tensor.GetEnumerator(); - - enumerator.Dispose(); - enumerator.Dispose(); - } - } -} diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorTestsBase.cs b/src/libraries/System.Numerics.Tensors/tests/TensorTestsBase.cs deleted file mode 100644 index 9774dd22662e6..0000000000000 --- a/src/libraries/System.Numerics.Tensors/tests/TensorTestsBase.cs +++ /dev/null @@ -1,187 +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.Collections.Generic; -using System.Linq; - -namespace System.Numerics.Tensors.Tests -{ - public class TensorTestsBase - { - public enum TensorType - { - Dense, - Sparse, - CompressedSparse - }; - - public class TensorConstructor - { - public TensorType TensorType { get; set; } - - public bool IsReversedStride { get; set; } - - public Tensor CreateFromArray(Array array) - { - switch (TensorType) - { - case TensorType.Dense: - return array.ToTensor(IsReversedStride); - case TensorType.Sparse: - return array.ToSparseTensor(IsReversedStride); - case TensorType.CompressedSparse: - return array.ToCompressedSparseTensor(IsReversedStride); - } - - throw new ArgumentException(nameof(TensorType)); - } - public Tensor CreateFromDimensions(ReadOnlySpan dimensions) - { - switch (TensorType) - { - case TensorType.Dense: - return new DenseTensor(dimensions, IsReversedStride); - case TensorType.Sparse: - return new SparseTensor(dimensions, IsReversedStride); - case TensorType.CompressedSparse: - return new CompressedSparseTensor(dimensions, IsReversedStride); - } - - throw new ArgumentException(nameof(TensorType)); - } - - public override string ToString() - { - return $"{TensorType}, {nameof(IsReversedStride)} = {IsReversedStride}"; - } - } - - private static TensorType[] s_tensorTypes = new[] - { - TensorType.Dense, - TensorType.Sparse, - TensorType.CompressedSparse - }; - - private static bool[] s_reverseStrideValues = new[] - { - false, - true - }; - - public static IEnumerable GetSingleTensorConstructors() - { - foreach (TensorType tensorType in s_tensorTypes) - { - foreach (bool isReversedStride in s_reverseStrideValues) - { - yield return new[] - { - new TensorConstructor() - { - TensorType = tensorType, - IsReversedStride = isReversedStride - } - }; - } - } - } - - public static IEnumerable GetDualTensorConstructors() - { - foreach (TensorType leftTensorType in s_tensorTypes) - { - foreach (TensorType rightTensorType in s_tensorTypes) - { - foreach (bool isLeftReversedStride in s_reverseStrideValues) - { - foreach (bool isRightReversedStride in s_reverseStrideValues) - { - yield return new[] - { - new TensorConstructor() - { - TensorType = leftTensorType, - IsReversedStride = isLeftReversedStride - }, - new TensorConstructor() - { - TensorType = rightTensorType, - IsReversedStride = isRightReversedStride - } - }; - } - } - } - } - } - - public static IEnumerable GetTensorAndResultConstructor() - { - foreach (TensorType leftTensorType in s_tensorTypes) - { - foreach (TensorType rightTensorType in s_tensorTypes) - { - foreach (bool isReversedStride in s_reverseStrideValues) - { - yield return new[] - { - new TensorConstructor() - { - TensorType = leftTensorType, - IsReversedStride = isReversedStride - }, - new TensorConstructor() - { - TensorType = rightTensorType, - IsReversedStride = isReversedStride - } - }; - } - } - } - } - - public static IEnumerable GetConstructedTensors() - { - foreach (var ctor in GetSingleTensorConstructors().Select(x => (TensorConstructor)x[0])) - { - yield return new object[] { ctor.CreateFromArray(Array.Empty()) }; - yield return new object[] { ctor.CreateFromArray(new[] { 7 }) }; - yield return new object[] { ctor.CreateFromArray(new[] { 7, 14 }) }; - yield return new object[] { ctor.CreateFromArray(new[] { 7, 14, 21 }) }; - yield return new object[] - { - ctor.CreateFromArray(new[,] - { - { 3, 6, 9 }, - { 5, 10, 15 }, - { 7, 14, 21 }, - { 11, 22, 33 } - }) - }; - } - } - - public static NativeMemory NativeMemoryFromArray(T[] array) - { - return NativeMemoryFromArray((Array)array); - } - - public static NativeMemory NativeMemoryFromArray(Array array) - { - // this silly method takes a managed array and copies it over to unmanaged memory, - // **only for test purposes** - - var memory = NativeMemory.Allocate(array.Length); - var span = memory.GetSpan(); - int index = 0; - foreach (T item in array) - { - span[index++] = item; - } - - return memory; - } - } -}