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);
+ }
+ }
+ }
+}