public static Span <T> MultiplyMatrices(IMatrix <T> Left, IMatrix <T> Right, TwoElementOperation <T> Multiplier, TwoElementOperation <T> Adder) { // to multiply two matrices we calc the dot product of the first row of the left with the first column of the right // we can either tranpose the whole matrix or use referenced mapped indices // try ref mapping T[] FinalMatrixArray = new T[Left.Rows * Right.Columns]; Span <T> FinalMatrixSpan = new(FinalMatrixArray); // transpose the matrix to avoid using slow indice mapping IMatrix <T> Transposed = Left.Transpose(); // once the matrix is transposed we can avoid math to mapp rows to columns // store the shapes of the matrxes to avoid slowness from using properties that have null checks (int Rows, int Columns)LeftShape = (Transposed.Rows, Transposed.Columns); (int Rows, int Columns)RightShape = (Right.Rows, Right.Columns); for (int RowIndex = 0; RowIndex < LeftShape.Rows; RowIndex++) { // store both rows directly in contigous memory Span <T> LeftSpan = new(Transposed[RowIndex]); Span <T> RightSpan = new(Right[RowIndex]); int index = 0; for (int LeftColumn = 0; LeftColumn < LeftShape.Columns; LeftColumn++) { for (int RightColumn = 0; RightColumn < RightShape.Columns; RightColumn++) { // multiply the two values and store them in a tmp var T Multiplied = Multiplier(ref LeftSpan[LeftColumn], ref RightSpan[RightColumn]); // add the value to the final array Adder(ref FinalMatrixSpan[index++], ref Multiplied); } } } return(FinalMatrixSpan); }
public static IMatrix <T> PerformTwoSidedNonMutableOperation(IMatrix <T> Left, IMatrix <T> Right, TwoElementOperation <T> Operation) { // duplicate the matrix to verify that we are not mutating the original matrix IMatrix <T> Dupe = Left.Duplicate(); // perform the possible mytating operation on all items int he matrix PerformTwoSidedMutableOperation(Dupe, Right, Operation); // return the duplicated matrix and not the original return(Dupe); }
public static IMatrix <T> PerformTwoSidedMutableOperation(IMatrix <T> Left, IMatrix <T> Right, TwoElementOperation <T> Operation) { // this function should only be used when the two matrices are the same shape(same row and column count) for (int row = 0; row < Left.Rows; row++) { Span <T> LeftRow = new(Left[row]); Span <T> RightRow = new(Right[row]); for (int column = 0; column < Left.Columns; column++) { Operation(ref LeftRow[column], ref RightRow[column]); } } return(Left); }