Passed
Push — main ( 71dcec...306c22 )
by Shubham
01:53
created

linAlg   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 49
c 1
b 0
f 0
dl 0
loc 99
rs 10
wmc 18

5 Methods

Rating   Name   Duplication   Size   Complexity  
A dotMatrix() 0 5 3
A dot() 0 10 5
A inverse() 0 17 4
A dotVector() 0 5 3
A pseudoInverse() 0 22 3
1
<?php
2
declare(strict_types=1);
3
namespace Np;
4
5
use Np\core\blas;
6
use Np\core\lapack;
7
/**
8
 * Linear Algebra
9
 * A fast lite memory efficient Scientific Computing for php
10
 * 
11
 * @package   NP
12
 * @category  Scientific Computing
13
 * @author    ghost (Shubham Chaudhary)
14
 * @email     [email protected]
15
 * @copyright (c) 2020-2021, Shubham Chaudhary
16
 */
17
trait linAlg {
18
    
19
    /**
20
     *  
21
     * get dot product of m.m | m.v | v.v
22
     * 
23
     * @param \Np\matrix|\Np\vector $d
24
     * @return matrix|vector
25
     */
26
    public function dot(matrix|vector $d): matrix|vector {
27
        if ($this instanceof matrix) {
28
            if ($d instanceof self) {
29
                return $this->dotMatrix($d);
30
            } else {
31
                return $this->dotVector($d);
32
            }
33
        } else {
34
            if ($this->checkDtype($this, $d) && $d instanceof vector) {
1 ignored issue
show
Bug introduced by
It seems like checkDtype() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

34
            if ($this->/** @scrutinizer ignore-call */ checkDtype($this, $d) && $d instanceof vector) {
Loading history...
35
                return blas::dot($this, $d);
36
            }
37
        }
38
    }
39
40
    /**
41
     * get matrix & matrix dot product
42
     * @param \Np\matrix $matrix
43
     * @return \Np\matrix
44
     */
45
    protected function dotMatrix(matrix $matrix): matrix {
46
        if ($this->checkDtype($this, $matrix) && $this->checkDimensions($this,$matrix)) {
1 ignored issue
show
Bug introduced by
It seems like checkDimensions() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
        if ($this->checkDtype($this, $matrix) && $this->/** @scrutinizer ignore-call */ checkDimensions($this,$matrix)) {
Loading history...
47
            $ar = self::factory($this->row, $this->col, $this->dtype);
48
            blas::gemm($this, $matrix, $ar);
49
            return $ar;
50
        }
51
    }
52
53
    /**
54
     * get dot product of matrix & a vector
55
     * @param \Np\vector $vector
56
     * @return \Np\vector
57
     */
58
    protected function dotVector(vector $vector): vector {
59
        if ($this->checkDtype($this, $vector) && $this->checkDimensions($vector, $this)) {
60
            $mvr = vector::factory($this->col, $this->dtype);
61
            blas::gemv($this, $vector, $mvr);
62
            return $mvr;
63
        }
64
    }
65
    
66
    /**
67
     *
68
     * Compute the multiplicative inverse of the matrix.
69
     * @return matrix
70
     */
71
    public function inverse(): matrix {
72
        if (!$this->isSquare()) {
1 ignored issue
show
Bug introduced by
It seems like isSquare() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

72
        if (!$this->/** @scrutinizer ignore-call */ isSquare()) {
Loading history...
73
            self::_err('Error::invalid Size of matrix!');
74
        }
75
        $imat = $this->copyMatrix();
0 ignored issues
show
Bug introduced by
It seems like copyMatrix() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

75
        /** @scrutinizer ignore-call */ 
76
        $imat = $this->copyMatrix();
Loading history...
76
        $ipiv = vector::factory($this->row, vector::INT);
77
        $lp = lapack::getrf($imat, $ipiv);
78
        if ($lp != 0) {
79
            return null;
80
        }
81
        $lp = lapack::getri($imat, $ipiv);
82
        if ($lp != 0) {
83
            return null;
84
        }
85
        unset($ipiv);
86
        unset($lp);
87
        return $imat;
88
    }
89
    
90
    /**
91
     * Compute the (Moore-Penrose) pseudo inverse of the general matrix.
92
     * @return matrix|null
93
     */
94
    public function pseudoInverse(): matrix|null {
95
        $k = min($this->row, $this->col);
96
        $s = vector::factory($k, $this->dtype);
97
        $u = self::factory($this->row, $this->row, $this->dtype);
98
        $vt = self::factory($this->col, $this->col, $this->dtype);
99
        $imat = $this->copyMatrix();
100
        $lp = lapack::gesdd($imat, $s, $u, $vt);
101
        if ($lp != 0) {
102
            return null;
103
        }
104
        for ($i = 0; $i < $k; ++$i) {
105
            blas::scale(1.0 / $s->data[$i], $vt->rowAsVector($i));
106
        }
107
        unset($imat);
108
        unset($k);
109
        unset($lp);
110
        unset($s);
111
        $mr = self::factory($this->col, $this->row, $this->dtype);
112
        blas::gemm($vt, $u, $mr);
113
        unset($u);
114
        unset($vt);
115
        return $mr;
116
    }
117
    
118
}
119