what is this?
 * Language: c# 11
 * Project Type: class library
 * Objective: generic class for Tensors, project aim to be used in large Tensors like LLMs.
 * + Class: 
- public partial class Tensor<T> : IDisposable, ICloneable, IEquatable<Tensor<T>>, IEnumerable<T> where T : unmanaged, INumber<T>, IExponentialFunctions<T>, ITrigonometricFunctions<T>, ILogarithmicFunctions<T>, IFloatingPointIeee754<T>, IRootFunctions<T>
 * + Fields:
- internal readonly T[] data;
- private readonly int[] shape;
- private readonly int[] strides;
- private readonly int totalSize;
- private bool disposed = false;
- private readonly bool isRowMajor;
- private readonly int offset; 
- private static readonly LruCache<(int[] ShapeA, int[] ShapeB), BroadcastCacheEntry> BroadcastCache = new LruCache<(int[], int[]), BroadcastCacheEntry>( capacity: 1024, comparer: new BroadcastCacheKeyComparer() );
 * + Properties:
- public int[] Shape
- public int[] Strides 
- public bool IsRowMajor 
- public int TotalSize 
- public static int ParallelizationThreshold 
- public static BackendType Backend 
- public int Rank 
- public T[] Data 
- public T this[params int[] indices]
- public T ScalarValue
 * + Initialization:
- public Tensor(bool isRowMajor, params int[] dimensions)
- private Tensor(T[] data, int[] shape, int[] strides, int totalSize, bool isRowMajor, bool disposed, int offset)
- public Tensor(params int[] dimensions) : this(true, dimensions)
- public Tensor(T scalarValue)
- public Tensor(T[] data, int[] shape, int[] strides)
- public Tensor(T[] dataArray, int[] dimensions)
- public Tensor(bool isRowMajor, T[] dataArray, int[] dimensions)
- public static Tensor<T> CreateColumnMajor(params int[] dimensions)
 * + Enums:
- public enum BackendType {CPU, GPU}
 * + Child Classes:
- private class BroadcastCacheKeyComparer : IEqualityComparer<(int[] ShapeA, int[] ShapeB)>
- private class IntArrayComparer : IEqualityComparer<int[]>
- private class LruCache<K, V> where K : notnull
 * + Structs:
- private struct BroadcastCacheEntry
 * + Methods:
- public void Fill(T value)
- public static Tensor<T> ZerosLike(Tensor<T> tensor)
- public IEnumerator<T> GetEnumerator()
- private void ComputeIndicesFromRawIndex(int rawIndex, int[] indices)
- IEnumerator IEnumerable.GetEnumerator()
- public void Dispose()
- ~Tensor()
- public Tensor<T> ElementWiseOperation(Tensor<T> other, Func<T, T, T> operation)
- public Tensor<T> Add(Tensor<T> other)
- public Tensor<T> Subtract(Tensor<T> other)
- public Tensor<T> Multiply(Tensor<T> other)
- public Tensor<T> Divide(Tensor<T> other)
- public static Tensor<T> operator +(Tensor<T> a, Tensor<T> b)
- public static Tensor<T> operator -(Tensor<T> a, Tensor<T> b)
- public static Tensor<T> operator *(Tensor<T> a, Tensor<T> b)
- public static Tensor<T> operator /(Tensor<T> a, Tensor<T> b)
- public Tensor<T> ScalarOperation(Func<T, T> operation)
- public Tensor<T> AddScalar(T scalar)
- public Tensor<T> SubtractScalar(T scalar)
- public Tensor<T> MultiplyScalar(T scalar)
- public Tensor<T> DivideScalar(T scalar)
- public static Tensor<T> operator +(Tensor<T> a, T scalar)
- public static Tensor<T> operator +(T scalar, Tensor<T> a)
- public static Tensor<T> operator -(Tensor<T> a, T scalar)
- public static Tensor<T> operator -(T scalar, Tensor<T> a)
- public static Tensor<T> operator *(Tensor<T> a, T scalar)
- public static Tensor<T> operator *(T scalar, Tensor<T> a)
- public static Tensor<T> operator /(Tensor<T> a, T scalar)
- public static Tensor<T> operator /(T scalar, Tensor<T> a)
- public void ElementWiseInPlaceOperation(Tensor<T> other, Func<T, T, T> operation)
- public void AddInPlace(Tensor<T> other)
- public void SubtractInPlace(Tensor<T> other)
- public void MultiplyInPlace(Tensor<T> other)
- public void DivideInPlace(Tensor<T> other)
- public void ScalarInPlaceOperation(Func<T, T> operation)
- public void MultiplyScalarInPlace(T scalar)
- public void AddScalarInPlace(T scalar)
- public void SubtractScalarInPlace(T scalar)
- public void DivideScalarInPlace(T scalar)
- public Tensor<T> MatMulSimple(Tensor<T> other)
- public Tensor<T> MatMul(Tensor<T> other)
- public Tensor<T> MatMulBatchOffset(Tensor<T> other)
- private int ComputeBatchOffset(int[] batchIndices, int[] batchShape, int[] strides)
- private static int GetBatchOffset(int[] batchIndices, int[] strides)
- public Tensor<T> Negate()
- public Tensor<T> Reciprocal()
- public Tensor<T> Log()
- public Tensor<T> OneSubtract()
- public Tensor<T> BroadcastTo(int[] targetShape)
- private static int[] BroadcastShapes(int[] shapeA, int[] shapeB)
- private static int[] GetBroadcastStrides(int[] originalShape, int[] resultShape, int[] originalStrides)
- private BroadcastCacheEntry GetOrAddBroadcastCache(int[] shapeA, int[] shapeB, int[] otherStrides)
- public void SetRow(int rowIndex, Tensor<T> rowTensor)
- public void EnsureNotDisposed()
- public T[] ToArray()
- public int CalculateFlatIndex(int[] indices)
- private int[] UnflattenIndex(int flatIndex, int[] shape)
- private static int GetFlatIndex(int[] indices, int[] strides, bool isRowMajor)
- private int CalculateResultIndex(int[] indices, int axis, int[] newStrides)
- private static int[] CalculateStrides(int[] shape, bool isRowMajor)
- private Tensor<T> Reduce(int axis, Func<T, T, T> reduction, T initial)
- private Tensor<T> Reduce(int axis, Func<T, T, T> reduction)
- public T Sum()
- public T Mean()
- public T Max()
- public T Min()
- public Tensor<T> Sum(int axis)
- public Tensor<T> Mean(int axis)
- public Tensor<T> Max(int axis)
- public Tensor<T> Min(int axis)
- public Tensor<T> Slice(int start, int length)
- public Tensor<T> Slice(params (int? Start, int? End, int? Step)[] slices)
- public void ClipInPlace(T minValue, T maxValue)
- public Tensor<T> Gather(int[] indices)
- public Tensor<T> Clip(T minValue, T maxValue)
- public Tensor<T> Repeat(int repeats, int axis)
- public Tensor<T> Copy()
- public object Clone()
- public bool Equals(Tensor<T>? other)
- public Tensor<T> Reshape(params int[] newShape)
- public Tensor<T> Transpose(int axis1, int axis2)
- public Tensor<T> ExpandDims(int axis)
- public Tensor<T> Squeeze(int? axis = null)
- public Tensor<T> Permute(params int[] axes)
- public Tensor<T> Flatten()
- public string Display()
- public void ToJson(Stream stream)
- public static Tensor<T> FromJson(Stream stream)
- public void ToBinary(Stream stream)
- public static Tensor<T> FromBinary(Stream stream)