public static GenTensor <T, TWrapper> MatrixPower(GenTensor <T, TWrapper> m, int power, Threading threading) { #if ALLOW_EXCEPTIONS if (!m.IsSquareMatrix) { throw new InvalidShapeException("Square matrix required"); } #endif if (power == 0) { return(Constructors <T, TWrapper> .CreateIdentityMatrix(m.Shape.shape[0])); } if (power < 0) { m = m.Forward(); m.InvertMatrix(); power *= -1; } if (power == 1) { return(m); } if (power == 2) { return(MatrixMultiplication <T, TWrapper> .Multiply(m, m, threading)); } var half = power / 2; var m1 = MatrixPower(m, half, threading); var dotted = MatrixMultiplication <T, TWrapper> .Multiply(m1, m1, threading); if (power % 2 == 0) { return(dotted); } else { return(MatrixMultiplication <T, TWrapper> .Multiply(dotted, m, threading)); } }
public static GenTensor <T, TWrapper> PiecewiseSubtract(GenTensor <T, TWrapper> a, T b, Threading threading) => Constructors <T, TWrapper> .CreateTensor(a.Shape, ind => default(TWrapper).Subtract(a[ind], b), threading);
public static GenTensor <T, TWrapper> PiecewiseSubtract( T a, GenTensor <T, TWrapper> b, Threading threading) => Constructors <T, TWrapper> .CreateTensor(b.Shape, ind => default(TWrapper).Subtract(a, b[ind]), threading);
internal static GenTensor <T, TWrapper> Multiply(GenTensor <T, TWrapper> a, GenTensor <T, TWrapper> b, Threading threading = Threading.Single) { #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 = Constructors <T, TWrapper> .CreateMatrix(width, height); var parallel = threading == Threading.Multi || (threading == Threading.Auto && a.Volume > 125); var aBlocks0 = a.blocks[0]; var aBlocks1 = a.blocks[1]; var bBlocks0 = b.blocks[0]; var bBlocks1 = b.blocks[1]; var aLinoffset = a.LinOffset; var bLinoffset = b.LinOffset; if (!parallel) { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var s = default(TWrapper).CreateZero(); for (int i = 0; i < row; i++) { var v1 = a.data[x * aBlocks0 + i * aBlocks1 + aLinoffset]; var v2 = b.data[i * bBlocks0 + y * bBlocks1 + bLinoffset]; s = default(TWrapper).Add(s, default(TWrapper).Multiply(v1, v2)); } res.data[x * height + y] = s; } } } else { Parallel.For(0, width, x => { for (int y = 0; y < height; y++) { var s = default(TWrapper).CreateZero(); for (int i = 0; i < row; i++) { var v1 = a.data[x * aBlocks0 + i * aBlocks1 + aLinoffset]; var v2 = b.data[i * bBlocks0 + y * bBlocks1 + bLinoffset]; s = default(TWrapper).Add(s, default(TWrapper).Multiply(v1, v2)); } res.data[x * height + y] = s; } }); } return(res); }