2024-02-02 14:09:07 +00:00
< ? php declare ( strict_types = 1 );
2022-07-05 15:55:47 +02:00
namespace DNW\Skills\Tests\Numerics ;
2010-09-01 08:21:10 -04:00
2022-07-05 15:33:34 +02:00
use DNW\Skills\Numerics\IdentityMatrix ;
use DNW\Skills\Numerics\Matrix ;
use DNW\Skills\Numerics\SquareMatrix ;
2024-02-01 10:50:18 +00:00
use PHPUnit\Framework\TestCase ;
2024-01-16 15:07:14 +00:00
use Exception ;
2010-09-01 08:21:10 -04:00
2023-08-04 07:22:05 +00:00
// phpcs:disable PSR2.Methods.FunctionCallSignature,Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma
2016-05-24 14:06:43 +02:00
class MatrixTest extends TestCase
2010-09-01 08:21:10 -04:00
{
2023-08-01 11:26:38 +00:00
public function testTwoByTwoDeterminant () : void
2010-09-01 08:21:10 -04:00
{
$a = new SquareMatrix ( 1 , 2 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( - 2 , $a -> getDeterminant ());
$b = new SquareMatrix ( 3 , 4 ,
2016-05-31 09:28:04 +02:00
5 , 6 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( - 2 , $b -> getDeterminant ());
$c = new SquareMatrix ( 1 , 1 ,
2016-05-31 09:28:04 +02:00
1 , 1 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( 0 , $c -> getDeterminant ());
$d = new SquareMatrix ( 12 , 15 ,
2016-05-31 09:28:04 +02:00
17 , 21 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( 12 * 21 - 15 * 17 , $d -> getDeterminant ());
}
2023-08-01 11:26:38 +00:00
public function testThreeByThreeDeterminant () : void
2010-09-01 08:21:10 -04:00
{
$a = new SquareMatrix ( 1 , 2 , 3 ,
2016-05-31 09:28:04 +02:00
4 , 5 , 6 ,
7 , 8 , 9 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( 0 , $a -> getDeterminant ());
$pi = new SquareMatrix ( 3 , 1 , 4 ,
2016-05-31 09:28:04 +02:00
1 , 5 , 9 ,
2 , 6 , 5 );
2010-09-01 08:21:10 -04:00
// Verified against http://www.wolframalpha.com/input/?i=determinant+%7B%7B3%2C1%2C4%7D%2C%7B1%2C5%2C9%7D%2C%7B2%2C6%2C5%7D%7D
$this -> assertEquals ( - 90 , $pi -> getDeterminant ());
}
2023-08-01 11:26:38 +00:00
public function testFourByFourDeterminant () : void
2010-09-01 08:21:10 -04:00
{
2022-07-05 15:55:47 +02:00
$a = new SquareMatrix ( 1 , 2 , 3 , 4 ,
2016-05-31 09:28:04 +02:00
5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 ,
13 , 14 , 15 , 16 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( 0 , $a -> getDeterminant ());
$pi = new SquareMatrix ( 3 , 1 , 4 , 1 ,
2016-05-31 09:28:04 +02:00
5 , 9 , 2 , 6 ,
5 , 3 , 5 , 8 ,
9 , 7 , 9 , 3 );
2010-09-01 08:21:10 -04:00
// Verified against http://www.wolframalpha.com/input/?i=determinant+%7B+%7B3%2C1%2C4%2C1%7D%2C+%7B5%2C9%2C2%2C6%7D%2C+%7B5%2C3%2C5%2C8%7D%2C+%7B9%2C7%2C9%2C3%7D%7D
$this -> assertEquals ( 98 , $pi -> getDeterminant ());
}
2016-05-24 13:59:35 +02:00
2023-08-01 11:26:38 +00:00
public function testEightByEightDeterminant () : void
2010-09-01 08:21:10 -04:00
{
2022-07-05 15:55:47 +02:00
$a = new SquareMatrix ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
2016-05-31 09:28:04 +02:00
9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 ,
17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 ,
25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 ,
33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 ,
41 , 42 , 32 , 44 , 45 , 46 , 47 , 48 ,
49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 ,
57 , 58 , 59 , 60 , 61 , 62 , 63 , 64 );
2010-09-01 08:21:10 -04:00
$this -> assertEquals ( 0 , $a -> getDeterminant ());
$pi = new SquareMatrix ( 3 , 1 , 4 , 1 , 5 , 9 , 2 , 6 ,
2016-05-31 09:28:04 +02:00
5 , 3 , 5 , 8 , 9 , 7 , 9 , 3 ,
2 , 3 , 8 , 4 , 6 , 2 , 6 , 4 ,
3 , 3 , 8 , 3 , 2 , 7 , 9 , 5 ,
0 , 2 , 8 , 8 , 4 , 1 , 9 , 7 ,
1 , 6 , 9 , 3 , 9 , 9 , 3 , 7 ,
5 , 1 , 0 , 5 , 8 , 2 , 0 , 9 ,
7 , 4 , 9 , 4 , 4 , 5 , 9 , 2 );
2010-09-01 08:21:10 -04:00
// Verified against http://www.wolframalpha.com/input/?i=det+%7B%7B3%2C1%2C4%2C1%2C5%2C9%2C2%2C6%7D%2C%7B5%2C3%2C5%2C8%2C9%2C7%2C9%2C3%7D%2C%7B2%2C3%2C8%2C4%2C6%2C2%2C6%2C4%7D%2C%7B3%2C3%2C8%2C3%2C2%2C7%2C9%2C5%7D%2C%7B0%2C2%2C8%2C8%2C4%2C1%2C9%2C7%7D%2C%7B1%2C6%2C9%2C3%2C9%2C9%2C3%2C7%7D%2C%7B5%2C1%2C0%2C5%2C8%2C2%2C0%2C9%7D%2C%7B7%2C4%2C9%2C4%2C4%2C5%2C9%2C2%7D%7D
$this -> assertEquals ( 1378143 , $pi -> getDeterminant ());
}
2010-09-01 22:17:00 -04:00
2023-08-01 11:26:38 +00:00
public function testEquals () : void
2010-09-01 22:17:00 -04:00
{
$a = new SquareMatrix ( 1 , 2 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-01 22:17:00 -04:00
$b = new SquareMatrix ( 1 , 2 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-01 22:17:00 -04:00
$this -> assertTrue ( $a -> equals ( $b ));
$c = Matrix :: fromRowsColumns ( 2 , 3 ,
2016-05-31 09:28:04 +02:00
1 , 2 , 3 ,
4 , 5 , 6 );
2010-09-01 22:17:00 -04:00
$d = Matrix :: fromRowsColumns ( 2 , 3 ,
2016-05-31 09:28:04 +02:00
1 , 2 , 3 ,
4 , 5 , 6 );
2010-09-01 22:17:00 -04:00
$this -> assertTrue ( $c -> equals ( $d ));
$e = Matrix :: fromRowsColumns ( 3 , 2 ,
2016-05-31 09:28:04 +02:00
1 , 4 ,
2 , 5 ,
3 , 6 );
2010-09-01 22:17:00 -04:00
$f = $e -> getTranspose ();
$this -> assertTrue ( $d -> equals ( $f ));
// Test rounding (thanks to nsp on GitHub for finding this case)
$g = new SquareMatrix ( 1 , 2.00000000000001 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-01 22:17:00 -04:00
$h = new SquareMatrix ( 1 , 2 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-01 22:17:00 -04:00
$this -> assertTrue ( $g -> equals ( $h ));
2024-01-16 15:07:14 +00:00
$i = new Matrix ( 1 , 2 , [[ 1 , 2 ]]);
$j = new Matrix ( 2 , 1 , [[ 1 ],[ 2 ]]);
$this -> assertFalse ( $i -> equals ( $j ));
$k = new Matrix ( 2 , 2 , [[ 1 , 2 ],[ 3 , 4 ]]);
$l = new Matrix ( 2 , 2 , [[ 4 , 3 ],[ 2 , 1 ]]);
$this -> assertFalse ( $k -> equals ( $l ));
2010-09-01 22:17:00 -04:00
}
2010-09-03 07:25:55 -04:00
2023-08-01 11:26:38 +00:00
public function testAdjugate () : void
2010-09-03 07:25:55 -04:00
{
// From Wikipedia: http://en.wikipedia.org/wiki/Adjugate_matrix
$a = new SquareMatrix ( 1 , 2 ,
2016-05-31 09:28:04 +02:00
3 , 4 );
2010-09-03 07:25:55 -04:00
2022-07-05 15:55:47 +02:00
$b = new SquareMatrix ( 4 , - 2 ,
- 3 , 1 );
2010-09-03 07:25:55 -04:00
$this -> assertTrue ( $b -> equals ( $a -> getAdjugate ()));
2016-05-24 13:59:35 +02:00
$c = new SquareMatrix ( - 3 , 2 , - 5 ,
2016-05-31 09:28:04 +02:00
- 1 , 0 , - 2 ,
3 , - 4 , 1 );
2010-09-03 07:25:55 -04:00
$d = new SquareMatrix ( - 8 , 18 , - 4 ,
2016-05-31 09:28:04 +02:00
- 5 , 12 , - 1 ,
2022-07-05 15:55:47 +02:00
4 , - 6 , 2 );
2010-09-03 07:25:55 -04:00
$this -> assertTrue ( $d -> equals ( $c -> getAdjugate ()));
}
2023-08-01 11:26:38 +00:00
public function testInverse () : void
2010-09-03 07:25:55 -04:00
{
// see http://www.mathwords.com/i/inverse_of_a_matrix.htm
$a = new SquareMatrix ( 4 , 3 ,
2016-05-31 09:28:04 +02:00
3 , 2 );
2010-09-03 07:25:55 -04:00
2016-05-31 09:28:04 +02:00
$b = new SquareMatrix ( - 2 , 3 ,
3 , - 4 );
2010-09-03 07:25:55 -04:00
$aInverse = $a -> getInverse ();
$this -> assertTrue ( $b -> equals ( $aInverse ));
$identity2x2 = new IdentityMatrix ( 2 );
$aaInverse = Matrix :: multiply ( $a , $aInverse );
$this -> assertTrue ( $identity2x2 -> equals ( $aaInverse ));
$c = new SquareMatrix ( 1 , 2 , 3 ,
2016-05-31 09:28:04 +02:00
0 , 4 , 5 ,
1 , 0 , 6 );
2010-09-03 07:25:55 -04:00
$cInverse = $c -> getInverse ();
$d = Matrix :: scalarMultiply (( 1.0 / 22 ), new SquareMatrix ( 24 , - 12 , - 2 ,
2016-05-31 09:28:04 +02:00
5 , 3 , - 5 ,
2022-07-05 15:55:47 +02:00
- 4 , 2 , 4 ));
2010-09-03 07:25:55 -04:00
$this -> assertTrue ( $d -> equals ( $cInverse ));
$identity3x3 = new IdentityMatrix ( 3 );
$ccInverse = Matrix :: multiply ( $c , $cInverse );
$this -> assertTrue ( $identity3x3 -> equals ( $ccInverse ));
}
2024-01-16 15:07:14 +00:00
public function testErrorDeterminant () : void
{
$this -> expectException ( Exception :: class );
$matrix = new Matrix ( 2 , 3 , [[ 1 , 2 , 3 ],[ 1 , 2 , 3 ]]);
$matrix -> getDeterminant ();
}
public function testErrorAdjugate () : void
{
$this -> expectException ( Exception :: class );
$matrix = new Matrix ( 2 , 3 , [[ 1 , 2 , 3 ],[ 1 , 2 , 3 ]]);
$matrix -> getAdjugate ();
}
public function testErrorAdd () : void
{
$this -> expectException ( Exception :: class );
$m1 = new Matrix ( 2 , 3 , [[ 1 , 2 , 3 ],[ 1 , 2 , 3 ]]);
$m2 = new Matrix ( 1 , 1 , [[ 1 , 1 ]]);
Matrix :: add ( $m1 , $m2 );
}
public function testErrorMultiply () : void
{
$this -> expectException ( Exception :: class );
$m1 = new Matrix ( 2 , 3 , [[ 1 , 2 , 3 ],[ 1 , 2 , 3 ]]);
$m2 = new Matrix ( 1 , 1 , [[ 1 , 1 ]]);
Matrix :: multiply ( $m1 , $m2 );
}
2022-07-05 15:55:47 +02:00
}
2023-08-04 07:22:05 +00:00
// phpcs:enable