nfTlWNl rn7pj-u8gB'֘;e4"oԗ|CA1vx4)xtDL\OM['2\X{T"w a1J'GSE=^ܘ6X/Qq0D;E|.4L*#@I+7N c]xvO܃u,RWլ+X4Kb3qhV'KH{Y/~mSX68͚qkz0Lbsz@E+L@NLn$`/^_=P:eTJF@b^N+7%Gcv/whBe7x0دN6O?^deN쵢_\ $m_L𽶮GЛp?M3 z# ;m+qnزG]jjqź%rT pa\2#N1;P^FV"{󰬆"q]ԥhsk='3 YŃ|;*b@p H-fC? ?|'j V, S<6F'(~H8#d>[jqź%rT y;'_J*w_)$9U-/%]  Tҫ1D&3py2^i\[p ĢQ$3Ysv8(wgɝILO]K۲,)e} jUXZhR'4=aNV(-YVSV&K Eq WE|ϴ;jqt%3-wŌ5AzwnнzC[l;k0wӤiNj@N&Jb$ۡHQ+2 ԋ'!^BNϕ >g?XdCe0pfME\ RD`Dtgw1*,c;SW%VQ|3%LMȉPBVEmП,WWk۹kx"-#/epufDв0\gw(_ "BY7K֜"T-!(]g}t06B&۪%ͺ׶>lQm'd%7}2y2^i\[p ĢQ$3&h#`gɝILO]K۲,)e} jUXZhR'4=aNV(-YVSV&KyPay[NmAt%3-58"}=3قXÖ]!N]yir$cl&N %ԶM͋Yb{n?%Xj@{qǕh|cu=BO&7n#I7h6@c-=׮==Em1X΍cE%% |GQd}G*ԯ!+ 8k< hDꟾȏi 9P\lHTeͣ05비Gj8@3EFw{i!kSPrҮZ[g'pF"idԾ)tt2{^_T &ur;~/ m"'BOt5{H:.|4=aNV(-YVSV&Km]:ܧq#:@S5)݇3_B[>@-xSc[f!4, 4AjeaTو&x qһd|y-N$TЁNXz" /;<\DI9naTⲻ ?{iΗ`fC(UrMsf4%Lg6;D%  ->OEaq"&v5uoxpĝCqt;JWO)fs#Wk6.mg^[51 4'YWe[ޢt߹m ;S9grG*Tsu'EZZ)AOA1/j"q4 !vVҾݤ?9ʬw/?XD=I/%W"uͬ@ TBirCJPYƃT"@S %9%FDj1pbk 3L cFI (focC`|XDbb<&QSQͰ)ÜG?.cu!K\ԲEO~nim6+}D> $`~"d>P?w`ԝ,n-~ԊBPrGLd X?gHwzQ(aq1S2MEZk5HS886M%1y ^,;ԅå5hhi4=R!M7, ųt_bK,N+?28ځX8 l쭏mL嬨e,,cU_!`{7*U !۰u"BQ[pH @F<2K2TAwլ;^pmmw/q9O˩Q6KwCۖ2Q2S<^'U:71- "q!R\ G^8ȼùEA=wv1(Ywa}ykWNT6 e5NAu%la俳箞9H= 0+MSTYԓMB5.W9JGb]\c Y\Tb^q4$Nha:6DYI|pŏNT2fU`}I<Ԃu6|eL} private function findPivot($column, array $luColumn): int { $pivot = $column; for ($row = $column + 1; $row < $this->rows; ++$row) { if (abs($luColumn[$row]) > abs($luColumn[$pivot])) { $pivot = $row; } } return $pivot; } private function pivotExchange($pivot, $column): void { for ($kValue = 0; $kValue < $this->columns; ++$kValue) { $tValue = $this->luMatrix[$pivot][$kValue]; $this->luMatrix[$pivot][$kValue] = $this->luMatrix[$column][$kValue]; $this->luMatrix[$column][$kValue] = $tValue; } $lValue = $this->pivot[$pivot]; $this->pivot[$pivot] = $this->pivot[$column]; $this->pivot[$column] = $lValue; } private function computeMultipliers($diagonal): void { if (($diagonal < $this->rows) && ($this->luMatrix[$diagonal][$diagonal] != 0.0)) { for ($row = $diagonal + 1; $row < $this->rows; ++$row) { $this->luMatrix[$row][$diagonal] /= $this->luMatrix[$diagonal][$diagonal]; } } } private function pivotB(Matrix $B): array { $X = []; foreach ($this->pivot as $rowId) { $row = $B->getRows($rowId + 1)->toArray(); $X[] = array_pop($row); } return $X; } /** * Solve A*X = B. * * @param Matrix $B a Matrix with as many rows as A and any number of columns * * @throws Exception * * @return Matrix X so that L*U*X = B(piv,:) */ public function solve(Matrix $B): Matrix { if ($B->rows !== $this->rows) { throw new Exception('Matrix row dimensions are not equal'); } if ($this->rows !== $this->columns) { throw new Exception('LU solve() only works on square matrices'); } if (!$this->isNonsingular()) { throw new Exception('Can only perform operation on singular matrix'); } // Copy right hand side with pivoting $nx = $B->columns; $X = $this->pivotB($B); // Solve L*Y = B(piv,:) for ($k = 0; $k < $this->columns; ++$k) { for ($i = $k + 1; $i < $this->columns; ++$i) { for ($j = 0; $j < $nx; ++$j) { $X[$i][$j] -= $X[$k][$j] * $this->luMatrix[$i][$k]; } } } // Solve U*X = Y; for ($k = $this->columns - 1; $k >= 0; --$k) { for ($j = 0; $j < $nx; ++$j) { $X[$k][$j] /= $this->luMatrix[$k][$k]; } for ($i = 0; $i < $k; ++$i) { for ($j = 0; $j < $nx; ++$j) { $X[$i][$j] -= $X[$k][$j] * $this->luMatrix[$i][$k]; } } } return new Matrix($X); } }