diff --git a/src/Numerics/LinearAlgebra/Matrix.Slice.cs b/src/Numerics/LinearAlgebra/Matrix.Slice.cs new file mode 100644 index 00000000..1797b2fe --- /dev/null +++ b/src/Numerics/LinearAlgebra/Matrix.Slice.cs @@ -0,0 +1,175 @@ +using System; + +namespace MathNet.Numerics.LinearAlgebra +{ + /// + /// This class is used for slice Matrix by using System.Range. + /// It is different from System.Range functions in the use of ".." syntax. + /// Because the when use ".." in array,like double[],the sliced array won't contain the end index. + /// However,in this Matrix,it will contain the end index. + /// + /// + public abstract partial class Matrix + { + /// + /// Get or Set the SubMatrix by [Range,Range] + /// For example: + /// Matrix mat = Matrix.Build.Dense(10,10); + /// mat[1..2,2..3]; + /// mat[1..2,^9..^1]; + /// mat[..,2..3]; + /// mat[1..2,2..3] = a new Matrix has the same dimension with this submatrix; + /// + /// the Row Range,it must contain more than one Row + /// the Column Range,it must contain more than one Column + /// A SubMatrix + public Matrix this[Range rowRange, Range columnRange] + { + get + { + int rowStartIndex = rowRange.Start.IsFromEnd ? RowCount - rowRange.Start.Value - 1 : rowRange.Start.Value; + int rowEndIndex = rowRange.End.IsFromEnd ? RowCount - rowRange.End.Value - 1 : rowRange.End.Value; + int rowCount = rowEndIndex - rowStartIndex + 1; + + if (rowCount <=1 || rowCount > RowCount) + { + throw new ArgumentException($"The argument Row Range:{rowRange} is wrong!"); + } + + int columnStartIndex = columnRange.Start.IsFromEnd ? ColumnCount - columnRange.Start.Value - 1 : columnRange.Start.Value; + int columnEndIndex = columnRange.End.IsFromEnd ? ColumnCount - columnRange.End.Value - 1 : columnRange.End.Value; + int columnCount = columnEndIndex - columnStartIndex + 1; + + if (columnCount <= 1 || columnCount > ColumnCount) + { + throw new ArgumentException($"The argument Column Range:{columnRange} is wrong!"); + } + + var result = Build.SameAs(this, rowCount, columnCount); + Storage.CopySubMatrixTo(result.Storage, rowStartIndex, 0, rowCount, columnStartIndex, 0, columnCount, ExistingData.AssumeZeros); + return result; + } + + set + { + int rowStartIndex = rowRange.Start.IsFromEnd ? RowCount - rowRange.Start.Value - 1 : rowRange.Start.Value; + int rowEndIndex = rowRange.End.IsFromEnd ? RowCount - rowRange.End.Value - 1 : rowRange.End.Value; + int rowCount = rowEndIndex - rowStartIndex + 1; + + if (rowCount <= 1 || rowCount > RowCount) + { + throw new ArgumentException($"The argument Row Range:{rowRange} is wrong!"); + } + + int columnStartIndex = columnRange.Start.IsFromEnd ? ColumnCount - columnRange.Start.Value - 1 : columnRange.Start.Value; + int columnEndIndex = columnRange.End.IsFromEnd ? ColumnCount - columnRange.End.Value - 1 : columnRange.End.Value; + int columnCount = columnEndIndex - columnStartIndex + 1; + + if (columnCount <= 1 || columnCount > ColumnCount) + { + throw new ArgumentException($"The argument Column Range:{columnRange} is wrong!"); + } + + value.Storage.CopySubMatrixTo(Storage, 0, rowStartIndex, rowCount, 0, columnStartIndex, columnCount); + } + } + + /// + /// Get or Set the Column SubVector of the Matrix + /// + /// the Row Range,it must contain more than one Row + /// the column index + /// a vector + public Vector this[Range rowRange, int columnIndex] + { + get + { + int rowStartIndex = rowRange.Start.IsFromEnd ? RowCount - rowRange.Start.Value - 1 : rowRange.Start.Value; + int rowEndIndex = rowRange.End.IsFromEnd ? RowCount - rowRange.End.Value - 1 : rowRange.End.Value; + int rowCount = rowEndIndex - rowStartIndex + 1; + + if (rowCount <= 1 || rowCount > RowCount) + { + throw new ArgumentException($"The argument Row Range:{rowRange} is wrong!"); + } + + if ((uint)columnIndex >= (uint)ColumnCount) + { + throw new ArgumentOutOfRangeException(nameof(columnIndex)); + } + + var ret = Vector.Build.SameAs(this, rowCount); + Storage.CopySubColumnTo(ret.Storage, columnIndex, rowStartIndex, 0, rowCount); + return ret; + } + + set + { + int rowStartIndex = rowRange.Start.IsFromEnd ? RowCount - rowRange.Start.Value - 1 : rowRange.Start.Value; + int rowEndIndex = rowRange.End.IsFromEnd ? RowCount - rowRange.End.Value - 1 : rowRange.End.Value; + int rowCount = rowEndIndex - rowStartIndex + 1; + + if (rowCount <= 1 || rowCount > RowCount) + { + throw new ArgumentException($"The argument Row Range:{rowRange} is wrong!"); + } + + if ((uint)columnIndex >= (uint)ColumnCount) + { + throw new ArgumentOutOfRangeException(nameof(columnIndex)); + } + + value.Storage.CopyToSubColumn(Storage, columnIndex, 0, rowStartIndex, rowCount); + } + } + + /// + /// Get or Set the row SubVector of the Matrix + /// + /// the column index + /// the Column Range,it must contain more than one Column + /// a vector + public Vector this[int rowIndex, Range columnRange] + { + get + { + int columnStartIndex = columnRange.Start.IsFromEnd ? ColumnCount - columnRange.Start.Value - 1 : columnRange.Start.Value; + int columnEndIndex = columnRange.End.IsFromEnd ? ColumnCount - columnRange.End.Value - 1 : columnRange.End.Value; + int columnCount = columnEndIndex - columnStartIndex + 1; + + if (columnCount <= 1 || columnCount > ColumnCount) + { + throw new ArgumentException($"The argument Column Range:{columnRange} is wrong!"); + } + + if ((uint)rowIndex >= (uint)RowCount) + { + throw new ArgumentOutOfRangeException(nameof(rowIndex)); + } + + var ret = Vector.Build.SameAs(this, columnCount); + Storage.CopySubRowTo(ret.Storage, rowIndex, columnStartIndex, 0, columnCount); + return ret; + } + + set + { + int columnStartIndex = columnRange.Start.IsFromEnd ? ColumnCount - columnRange.Start.Value - 1 : columnRange.Start.Value; + int columnEndIndex = columnRange.End.IsFromEnd ? ColumnCount - columnRange.End.Value - 1 : columnRange.End.Value; + int columnCount = columnEndIndex - columnStartIndex + 1; + + if (columnCount <= 1 || columnCount > ColumnCount) + { + throw new ArgumentException($"The argument Column Range:{columnRange} is wrong!"); + } + + if ((uint)rowIndex >= (uint)RowCount) + { + throw new ArgumentOutOfRangeException(nameof(rowIndex)); + } + + value.Storage.CopyToSubRow(Storage, rowIndex, 0, columnStartIndex, columnCount); + } + } + } +}