/// <summary> /// [i, j, k...]th element of the resulting tensor is /// operation(a[i, j, k...], b[i, j, k...]) /// </summary> public static GenTensor <T> Zip(GenTensor <T> a, GenTensor <T> b, Func <T, T, T> operation) { #if ALLOW_EXCEPTIONS if (a.Shape != b.Shape) { throw new InvalidShapeException("Arguments should be of the same shape"); } #endif var res = new GenTensor <T>(a.Shape); if (res.Shape.shape.Length == 1) { for (int x = 0; x < res.Shape.shape[0]; x++) { res.Data[x] = ConstantsAndFunctions <T> .Forward( operation(a.GetValueNoCheck(x), b.GetValueNoCheck(x))); } } else if (res.Shape.shape.Length == 2) { for (int x = 0; x < res.Shape.shape[0]; x++) { for (int y = 0; y < res.Shape.shape[1]; y++) { res.Data[x * res.Blocks[0] + y] = ConstantsAndFunctions <T> .Forward( operation(a.GetValueNoCheck(x, y), b.GetValueNoCheck(x, y))); } } } else if (res.Shape.shape.Length == 3) { for (int x = 0; x < res.Shape.shape[0]; x++) { for (int y = 0; y < res.Shape.shape[1]; y++) { for (int z = 0; z < res.Shape.shape[2]; z++) { res.Data[x * res.Blocks[0] + y * res.Blocks[1] + z] = ConstantsAndFunctions <T> .Forward( operation(a.GetValueNoCheck(x, y, z), b.GetValueNoCheck(x, y, z))); } } } } else { foreach (var index in res.IterateOverElements()) { res.SetValueNoCheck(ConstantsAndFunctions <T> .Forward( operation(a.GetValueNoCheck(index), b.GetValueNoCheck(index))), index); } } return(res); }
/// <summary> /// Finds matrix multiplication result /// a and b are matrices /// a.Shape[1] should be equal to b.Shape[0] /// the resulting matrix is [a.Shape[0] x b.Shape[1]] shape /// /// O(N^3) /// </summary> public static GenTensor <T> MatrixMultiply(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (!a.IsMatrix || !b.IsMatrix) { throw new InvalidShapeException($"Both {nameof(a)} and {nameof(b)} should be matrices"); } if (a.Shape[1] != b.Shape[0]) { throw new InvalidShapeException($"{nameof(a)}'s height must be equal to {nameof(b)}'s width"); } #endif var width = a.Shape[0]; var height = b.Shape[1]; var row = a.Shape[1]; var res = CreateMatrix(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var s = ConstantsAndFunctions <T> .CreateZero(); for (int i = 0; i < row; i++) { var v1 = a.GetValueNoCheck(x, i); var v2 = b.GetValueNoCheck(i, y); s = ConstantsAndFunctions <T> .Add(s, ConstantsAndFunctions <T> .Multiply(v1, v2)); } res.SetValueNoCheck(s, x, y); } } return(res); }
private static void GetCofactor(GenTensor <T> a, GenTensor <T> temp, int rowId, int colId, int diagLength) { int i = 0, j = 0; for (int row = 0; row < diagLength; row++) { for (int col = 0; col < diagLength; col++) { if (row != rowId && col != colId) { temp.SetValueNoCheck(a.GetValueNoCheck(row, col), i, j++); if (j == diagLength - 1) { j = 0; i++; } } } } }
public static GenTensor <T> Concat(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (a.Shape.SubShape(1, 0) != b.Shape.SubShape(1, 0)) { throw new InvalidShapeException("Excluding the first dimension, all others should match"); } #endif if (a.IsVector) { var resultingVector = GenTensor <T> .CreateVector(a.Shape.shape[0] + b.Shape.shape[0]); for (int i = 0; i < a.Shape.shape[0]; i++) { resultingVector.SetValueNoCheck(ConstantsAndFunctions <T> .Forward(a.GetValueNoCheck(i)), i); } for (int i = 0; i < b.Shape.shape[0]; i++) { resultingVector.SetValueNoCheck(ConstantsAndFunctions <T> .Forward(b.GetValueNoCheck(i)), i + a.Shape.shape[0]); } return(resultingVector); } else { var newShape = a.Shape.Copy(); newShape.shape[0] = a.Shape.shape[0] + b.Shape.shape[0]; var res = new GenTensor <T>(newShape); for (int i = 0; i < a.Shape.shape[0]; i++) { res.SetSubtensor(a.GetSubtensor(i), i); } for (int i = 0; i < b.Shape.shape[0]; i++) { res.SetSubtensor(b.GetSubtensor(i), i + a.Shape.shape[0]); } return(res); } }
/// <summary> /// Finds the scalar product of two vectors /// /// O(N) /// </summary> public static T VectorDotProduct(GenTensor <T> a, GenTensor <T> b) { #if ALLOW_EXCEPTIONS if (!a.IsVector || !b.IsVector) { throw new InvalidShapeException($"{nameof(a)} and {nameof(b)} should be vectors"); } if (a.Shape[0] != b.Shape[0]) { throw new InvalidShapeException($"{nameof(a)}'s length should be the same as {nameof(b)}'s"); } #endif var res = ConstantsAndFunctions <T> .CreateZero(); for (int i = 0; i < a.Shape[0]; i++) { res = ConstantsAndFunctions <T> .Add(res, ConstantsAndFunctions <T> .Multiply(a.GetValueNoCheck(i), b.GetValueNoCheck(i))); } return(res); }
public bool Equals(GenTensor <T> obj) { if (obj.Shape != Shape) { return(false); } foreach (var(index, _) in obj.Iterate()) { if (!ConstantsAndFunctions <T> .AreEqual(this.GetValueNoCheck(index), obj.GetValueNoCheck(index))) { return(false); } } return(true); }