Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Sources/AngouriMath/Core/Entity/Omni/Entity.Matrix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,39 @@ private static Matrix ToMatrix(Entity entity)
/// </summary>
public Entity this[int x, int y] => InnerMatrix[x, y];

/// <summary>
/// The submatrix spanned by the given rows and columns, for example
/// <code>a[1.., ..]</code> for every row of a matrix but the first, or
/// <code>a[..2, 1..3]</code> for the first two rows of its second and third columns.
/// </summary>
/// <remarks>
/// Both extents have to be written out. A matrix indexed by one number gives a row
/// while a vector indexed by one number gives an element, so a single range would
/// have to mean one thing here and the other there --
/// https://github.com/asc-community/AngouriMath/issues/443.
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either range reaches past the matrix.
/// </exception>
/// <exception cref="InvalidMatrixOperationException">
/// Thrown if either range is empty, since a matrix has at least one row and one
/// column.
/// </exception>
public Matrix this[Range rows, Range columns]
{
get
{
var (firstRow, rowCount) = rows.GetOffsetAndLength(RowCount);
var (firstColumn, columnCount) = columns.GetOffsetAndLength(ColumnCount);
if (rowCount is 0 || columnCount is 0)
throw new InvalidMatrixOperationException(
$"A {rowCount}x{columnCount} matrix cannot be created; both extents must be non-empty");
return new Matrix(
indices => InnerMatrix[firstRow + indices[0], firstColumn + indices[1]],
rowCount, columnCount);
}
}

/// <summary>
/// Checks whether the matrix only contains one
/// column.
Expand Down
98 changes: 98 additions & 0 deletions Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// Copyright (c) 2019-2022 Angouri.
// AngouriMath is licensed under MIT.
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
// Website: https://am.angouri.org.
//

using System;
using AngouriMath;
using AngouriMath.Core.Exceptions;
using Xunit;

namespace AngouriMath.Tests.Algebra
{
/// <summary>
/// Taking part of a matrix by range, as asked for in
/// https://github.com/asc-community/AngouriMath/issues/443.
/// </summary>
public sealed class MatrixRangeTest
{
private static readonly Entity.Matrix ThreeByThree = MathS.Matrices.Matrix(3, 3,
1, 2, 3,
4, 5, 6,
7, 8, 9
);

private static readonly Entity.Matrix Column = MathS.Matrices.Vector(1, 2, 3);

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 27 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

[Fact]
public void EveryRowButTheFirst() =>
Assert.Equal(MathS.Matrices.Matrix(2, 3,
4, 5, 6,
7, 8, 9), ThreeByThree[1.., ..]);

[Fact]
public void EveryColumnButTheLast() =>
Assert.Equal(MathS.Matrices.Matrix(3, 2,
1, 2,
4, 5,
7, 8), ThreeByThree[.., ..2]);

[Fact]
public void AnInnerBlock() =>
Assert.Equal(MathS.Matrices.Matrix(2, 2,
5, 6,
8, 9), ThreeByThree[1..3, 1..3]);

[Fact]
public void CountedFromTheEnd() =>
Assert.Equal(MathS.Matrices.Matrix(1, 1, 9), ThreeByThree[^1.., ^1..]);

[Fact]
public void TheWholeMatrix() =>
Assert.Equal(ThreeByThree, ThreeByThree[.., ..]);

// A vector is a matrix of one column, so the second extent is what a vector is cut by
// rows with, and it has only the one column to ask for.
[Fact]
public void PartOfAVector() =>
Assert.Equal(MathS.Matrices.Vector(2, 3), Column[1.., ..]);

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

Check warning on line 60 in Sources/Tests/UnitTests/Algebra/MatrixRangeTest.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

'MathS.Matrices.Vector(params Entity[])' is obsolete: 'Use MathS.Vector instead'

// The result is a matrix in its own right and nothing of the original is shared with
// it, so what is read out of it does not depend on the order the two were built in.
[Fact]
public void TheResultIsAMatrixLikeAnyOther()
{
var block = ThreeByThree[..2, 1..];
Assert.Equal(2, block.RowCount);
Assert.Equal(2, block.ColumnCount);
Assert.Equal((Entity)6, block[1, 1]);
Assert.Equal(MathS.Matrices.Matrix(2, 2,
2, 5,
3, 6), block.T);
}

[Fact]
public void SymbolicEntriesAreCarriedOverUntouched() =>
Assert.Equal(
MathS.Matrices.Matrix(1, 2, "y", "x + 1"),
MathS.Matrices.Matrix(2, 2,
"x", "y",
"y", "x + 1")[1.., ..][.., ..]);

[Fact]
public void AnEmptyRangeIsRefused()
{
Assert.Throws<InvalidMatrixOperationException>(() => ThreeByThree[1..1, ..]);
Assert.Throws<InvalidMatrixOperationException>(() => ThreeByThree[.., 2..2]);
}

[Fact]
public void ARangeReachingPastTheMatrixIsRefused()
{
Assert.Throws<ArgumentOutOfRangeException>(() => ThreeByThree[..4, ..]);
Assert.Throws<ArgumentOutOfRangeException>(() => ThreeByThree[.., 1..5]);
}
}
}
Loading