Skip to content

Commit a69e54e

Browse files
committed
Implemented matrix determinant
1 parent e163f30 commit a69e54e

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

src/Matrix.php

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,30 @@ public function inverse() : self
621621
return self::quick($c);
622622
}
623623

624+
/**
625+
* Calculate the determinant of the matrix.
626+
*
627+
* @throws \RuntimeException
628+
* @return float
629+
*/
630+
public function det() : float
631+
{
632+
if ($this->m !== $this->n) {
633+
throw new RuntimeException('Determinant is not defined for a'
634+
. ' non square matrix.');
635+
}
636+
637+
list($b, $swaps) = $this->ref();
638+
639+
$dHat = 1.;
640+
641+
for ($i = 0; $i < $this->m; $i++) {
642+
$dHat *= $b[$i][$i];
643+
}
644+
645+
return (-1.) ** $swaps * $dHat;
646+
}
647+
624648
/**
625649
* Return the elementwise reciprocal of the matrix.
626650
*
@@ -725,16 +749,19 @@ public function dot(Vector $b) : self
725749

726750
/**
727751
* Calculate the row echelon form of the matrix using Gaussian elimination.
752+
* Return the matrix in ref and the number of swaps in a tuple.
728753
*
729754
* @throws \RuntimeException
730-
* @return self
755+
* @return array
731756
*/
732-
public function ref() : self
757+
public function ref() : array
733758
{
734759
$minDim = min($this->shape());
735760

736761
$b = $this->a;
737762

763+
$swaps = 0;
764+
738765
for ($k = 0; $k < $minDim; $k++) {
739766
$index = $k;
740767

@@ -754,6 +781,8 @@ public function ref() : self
754781

755782
$b[$k] = $b[$index];
756783
$b[$index] = $temp;
784+
785+
$swaps++;
757786
}
758787

759788
$diag = $b[$k][$k];
@@ -769,7 +798,7 @@ public function ref() : self
769798
}
770799
}
771800

772-
return self::quick($b);
801+
return [self::quick($b), $swaps];
773802
}
774803

775804
/**
@@ -779,7 +808,9 @@ public function ref() : self
779808
*/
780809
public function rref() : self
781810
{
782-
$b = $this->ref()->asArray();
811+
list($b, $swaps) = $this->ref();
812+
813+
$b = $b->asArray();
783814

784815
$row = $col = 0;
785816

src/Vector.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ public static function range(float $start, float $end, float $interval = 1.) : s
185185
*/
186186
public static function linspace(float $start, float $end, int $n) : self
187187
{
188-
$interval = abs($end - $start) / ($n - 1);
188+
$range = abs($end - $start);
189+
190+
$interval = ($range / ($n - 1)) - (self::EPSILON * $range);
189191

190192
return self::range($start, $end, $interval);
191193
}

tests/MatrixTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,12 @@ public function test_inverse()
344344
$this->assertEquals($y, $z->asArray());
345345
}
346346

347+
public function test_det()
348+
{
349+
$this->assertEquals(-5301.999999999999, $this->a->det());
350+
$this->assertEquals(-544., $this->c->det());
351+
}
352+
347353
public function test_reciprocal()
348354
{
349355
$z = $this->a->reciprocal();
@@ -385,7 +391,7 @@ public function test_reduce()
385391

386392
public function test_ref()
387393
{
388-
$z = $this->a->ref();
394+
list($z, $swaps) = $this->a->ref();
389395

390396
$y = [
391397
[22, -17, 12],

tests/VectorTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ public function test_build_linspace()
105105
{
106106
$z = Vector::linspace(-5, 5, 9);
107107

108-
$y = [-5., -3.75, -2.5, -1.25, 0., 1.25, 2.5, 3.75, 5.];
108+
$y = [
109+
-5., -3.7500001000000003, -2.5000002, -1.2500003, -4.0000000023354687E-7,
110+
1.2499994999999995, 2.4999994, 3.749999299999999, 4.9999991999999995,
111+
];
109112

110113
$this->assertInstanceOf(Vector::class, $z);
111114
$this->assertCount(9, $z);

0 commit comments

Comments
 (0)