internal sealed override MatrixImplementor <double> this[int rowIndex, string columnIndexes]
        {
            get
            {
                // Check if any row index is outside the range defined by matrix dimensions
                if (rowIndex < 0 || this.numberOfRows <= rowIndex)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(rowIndex),
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS"));
                }

                int thisNumberOfRows = this.numberOfRows;

                int      columnsLength = this.numberOfColumns;
                var      subMatrix     = new DenseDoubleMatrixImplementor(1, columnsLength);
                double[] subStorage    = subMatrix.storage;

                double[] thisStorage = this.storage;

                int offset;

                for (int j = 0; j < columnsLength; j++)
                {
                    offset        = thisNumberOfRows * j;
                    subStorage[j] = thisStorage[rowIndex + offset];
                }

                return(subMatrix);
            }
            set
            {
                // Check if any row index is outside the range defined by matrix dimensions
                if (rowIndex < 0 || this.numberOfRows <= rowIndex)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(rowIndex),
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS"));
                }

                // Test for mismatched matrix dimensions
                ImplementationServices.ThrowOnMismatchedMatrixDimensions(
                    1, this.numberOfColumns, value);

                MatrixImplementor <double> sourceImplementor;

                // if the source is this, clone the data before writing
                if (object.ReferenceEquals(this, value))
                {
                    sourceImplementor = (MatrixImplementor <double>)value.Clone();
                }
                else
                {
                    sourceImplementor = value;
                }

                int thisNumberOfRows = this.numberOfRows;

                int offset;
                int columnsLength = this.numberOfColumns;

                switch (sourceImplementor.StorageScheme)
                {
                case StorageScheme.CompressedRow:
                {
                    var source = (SparseCsr3DoubleMatrixImplementor)sourceImplementor;

                    for (int j = 0; j < columnsLength; j++)
                    {
                        offset = thisNumberOfRows * j;
                        this.storage[rowIndex + offset] = source.GetValue(j);
                    }
                }
                break;

                case StorageScheme.Dense:
                {
                    var      source        = (DenseDoubleMatrixImplementor)sourceImplementor;
                    double[] sourceStorage = source.storage;

                    for (int j = 0; j < columnsLength; j++)
                    {
                        offset = thisNumberOfRows * j;
                        this.storage[rowIndex + offset] = sourceStorage[j];
                    }
                }
                break;
                }
            }
        }
        internal sealed override MatrixImplementor <double> this[string rowIndexes, IndexCollection columnIndexes]
        {
            get
            {
                // Check if any column index is outside the range defined by matrix dimensions
                if (columnIndexes.maxIndex >= this.numberOfColumns)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(columnIndexes),
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS"));
                }

                int thisNumberOfRows = this.numberOfRows;

                int[]    columns       = columnIndexes.indexes;
                int      rowsLength    = thisNumberOfRows;
                int      columnsLength = columns.Length;
                var      subMatrix     = new DenseDoubleMatrixImplementor(rowsLength, columnsLength);
                double[] subStorage    = subMatrix.storage;

                double[] thisStorage = this.storage;

                int offset, index = 0;

                for (int j = 0; j < columnsLength; j++)
                {
                    offset = thisNumberOfRows * columns[j];
                    for (int i = 0; i < rowsLength; i++, index++)
                    {
                        subStorage[index] = thisStorage[i + offset];
                    }
                }

                return(subMatrix);
            }
            set
            {
                // Check if any column index is outside the range defined by matrix dimensions
                if (columnIndexes.maxIndex >= this.numberOfColumns)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(columnIndexes),
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS"));
                }

                int thisNumberOfRows = this.numberOfRows;

                // Test for mismatched matrix dimensions
                ImplementationServices.ThrowOnMismatchedMatrixDimensions(thisNumberOfRows, columnIndexes.Count, value);

                MatrixImplementor <double> sourceImplementor;

                // if the source is this, clone the data before writing
                if (object.ReferenceEquals(this, value))
                {
                    sourceImplementor = (MatrixImplementor <double>)value.Clone();
                }
                else
                {
                    sourceImplementor = value;
                }

                int   offset;
                int[] columns = columnIndexes.indexes;

                switch (sourceImplementor.StorageScheme)
                {
                case StorageScheme.CompressedRow:
                {
                    var source       = (SparseCsr3DoubleMatrixImplementor)sourceImplementor;
                    var sourceValues = source.values;

                    for (int j = 0; j < columns.Length; j++)
                    {
                        offset = thisNumberOfRows * columns[j];
                        for (int i = 0; i < thisNumberOfRows; i++)
                        {
                            if (source.TryGetPosition(i, j, out int index))
                            {
                                this.storage[i + offset] = sourceValues[index];
                            }
                        }
                    }
                }
                break;

                case StorageScheme.Dense:
                {
                    var      source        = (DenseDoubleMatrixImplementor)sourceImplementor;
                    double[] sourceStorage = source.storage;
                    int      index         = 0;
                    for (int j = 0; j < columns.Length; j++)
                    {
                        offset = thisNumberOfRows * columns[j];
                        for (int i = 0; i < thisNumberOfRows; i++, index++)
                        {
                            this.storage[i + offset] = sourceStorage[index];
                        }
                    }
                }
                break;
                }
            }
        }
        internal sealed override MatrixImplementor <double> this[string rowIndexes, string columnIndexes]
        {
            get
            {
                int thisNumberOfRows = this.numberOfRows;

                int      rowsLength    = thisNumberOfRows;
                int      columnsLength = this.numberOfColumns;
                var      subMatrix     = new DenseDoubleMatrixImplementor(rowsLength, columnsLength);
                double[] subStorage    = subMatrix.storage;

                double[] thisStorage = this.storage;

                int offset, index = 0;

                for (int j = 0; j < columnsLength; j++)
                {
                    offset = thisNumberOfRows * j;
                    for (int i = 0; i < rowsLength; i++, index++)
                    {
                        subStorage[index] = thisStorage[i + offset];
                    }
                }

                return(subMatrix);
            }
            set
            {
                // Test for mismatched matrix dimensions
                ImplementationServices.ThrowOnMismatchedMatrixDimensions(this.numberOfRows, this.numberOfColumns, value);

                // if the source is this, nothing has to be done
                if (object.ReferenceEquals(this, value))
                {
                    return;
                }

                MatrixImplementor <double> sourceImplementor = value;

                int offset;

                int thisNumberOfRows = this.numberOfRows;
                int rowsLength       = thisNumberOfRows;
                int columnsLength    = this.numberOfColumns;

                switch (sourceImplementor.StorageScheme)
                {
                case StorageScheme.CompressedRow:
                {
                    var source       = (SparseCsr3DoubleMatrixImplementor)sourceImplementor;
                    var sourceValues = source.values;

                    for (int j = 0; j < columnsLength; j++)
                    {
                        offset = thisNumberOfRows * j;
                        for (int i = 0; i < rowsLength; i++)
                        {
                            if (source.TryGetPosition(i, j, out int index))
                            {
                                this.storage[i + offset] = sourceValues[index];
                            }
                        }
                    }
                }
                break;

                case StorageScheme.Dense:
                {
                    var      source        = (DenseDoubleMatrixImplementor)sourceImplementor;
                    double[] sourceStorage = source.storage;
                    int      index         = 0;
                    for (int j = 0; j < columnsLength; j++)
                    {
                        offset = thisNumberOfRows * j;
                        for (int i = 0; i < rowsLength; i++, index++)
                        {
                            this.storage[i + offset] = sourceStorage[index];
                        }
                    }
                }
                break;
                }
            }
        }