1 | <?php |
||
2 | |||
3 | /** |
||
4 | * JPGraph v4.0.3 |
||
5 | */ |
||
6 | |||
7 | namespace Amenadiel\JpGraph\Util; |
||
8 | |||
9 | 1 | define('__LR_EPSILON', 1.0e-8); |
|
10 | /** |
||
11 | * @class LinearRegression |
||
12 | */ |
||
13 | class LinearRegression |
||
14 | { |
||
15 | private $ix = []; |
||
16 | private $iy = []; |
||
17 | private $ib = 0; |
||
18 | private $ia = 0; |
||
19 | private $icalculated = false; |
||
20 | public $iDet = 0; |
||
21 | public $iCorr = 0; |
||
22 | public $iStdErr = 0; |
||
23 | |||
24 | 1 | public function __construct($aDataX, $aDataY) |
|
25 | { |
||
26 | 1 | if (safe_count($aDataX) !== safe_count($aDataY)) { |
|
27 | JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.'); |
||
28 | } |
||
29 | 1 | $this->ix = $aDataX; |
|
30 | 1 | $this->iy = $aDataY; |
|
31 | 1 | } |
|
32 | |||
33 | 1 | public function Calc() |
|
34 | { |
||
35 | 1 | $this->icalculated = true; |
|
36 | |||
37 | 1 | $n = safe_count($this->ix); |
|
38 | 1 | $sx2 = 0; |
|
39 | 1 | $sy2 = 0; |
|
40 | 1 | $sxy = 0; |
|
41 | 1 | $sx = 0; |
|
42 | 1 | $sy = 0; |
|
43 | |||
44 | 1 | for ($i = 0; $i < $n; ++$i) { |
|
45 | 1 | $sx2 += $this->ix[$i] * $this->ix[$i]; |
|
46 | 1 | $sy2 += $this->iy[$i] * $this->iy[$i]; |
|
47 | 1 | $sxy += $this->ix[$i] * $this->iy[$i]; |
|
48 | 1 | $sx += $this->ix[$i]; |
|
49 | 1 | $sy += $this->iy[$i]; |
|
50 | } |
||
51 | |||
52 | 1 | if ($n * $sx2 - $sx * $sx > __LR_EPSILON) { |
|
53 | 1 | $this->ib = ($n * $sxy - $sx * $sy) / ($n * $sx2 - $sx * $sx); |
|
54 | 1 | $this->ia = ($sy - $this->ib * $sx) / $n; |
|
55 | |||
56 | 1 | $sx = $this->ib * ($sxy - $sx * $sy / $n); |
|
57 | 1 | $sy2 = $sy2 - $sy * $sy / $n; |
|
58 | 1 | $sy = $sy2 - $sx; |
|
59 | |||
60 | 1 | $this->iDet = $sx / $sy2; |
|
61 | 1 | $this->iCorr = sqrt($this->iDet); |
|
62 | 1 | if ($n > 2) { |
|
63 | 1 | $this->iStdErr = sqrt($sy / ($n - 2)); |
|
64 | } else { |
||
65 | 1 | $this->iStdErr = NAN; |
|
66 | } |
||
67 | } else { |
||
68 | $this->ib = 0; |
||
69 | $this->ia = 0; |
||
70 | } |
||
71 | 1 | } |
|
72 | |||
73 | public function GetAB() |
||
74 | { |
||
75 | if ($this->icalculated == false) { |
||
0 ignored issues
–
show
|
|||
76 | $this->Calc(); |
||
77 | } |
||
78 | |||
79 | return [$this->ia, $this->ib]; |
||
80 | } |
||
81 | |||
82 | 1 | public function GetStat() |
|
83 | { |
||
84 | 1 | if ($this->icalculated == false) { |
|
0 ignored issues
–
show
|
|||
85 | 1 | $this->Calc(); |
|
86 | } |
||
87 | |||
88 | 1 | return [$this->iStdErr, $this->iCorr, $this->iDet]; |
|
89 | } |
||
90 | |||
91 | 1 | public function GetY($aMinX, $aMaxX, $aStep = 1) |
|
92 | { |
||
93 | 1 | if ($this->icalculated == false) { |
|
0 ignored issues
–
show
|
|||
94 | $this->Calc(); |
||
95 | } |
||
96 | |||
97 | 1 | $yy = []; |
|
98 | 1 | $i = 0; |
|
99 | 1 | for ($x = $aMinX; $x <= $aMaxX; $x += $aStep) { |
|
100 | 1 | $xx[$i] = $x; |
|
101 | 1 | $yy[$i++] = $this->ia + $this->ib * $x; |
|
102 | } |
||
103 | |||
104 | 1 | return [$xx, $yy]; |
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||
105 | } |
||
106 | } |
||
107 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.