| Source for file EigenvalueDecomposition.phpDocumentation is available at EigenvalueDecomposition.php 
 *     Class to obtain eigenvalues and eigenvectors of a real matrix. *     If A is symmetric, then A = V*D*V' where the eigenvalue matrix D *     is diagonal and the eigenvector matrix V is orthogonal (i.e. *     A = V.times(D.times(V.transpose())) and V.times(V.transpose()) *     equals the identity matrix). *     If A is not symmetric, then the eigenvalue matrix D is block diagonal *     with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues, *     lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The *     columns of V represent the eigenvectors in the sense that A*V = V*D, *     i.e. A.times(V) equals V.times(D).  The matrix V may be badly *     conditioned, or even singular, so the validity of the equation *     A = V*D*inverse(V) depends upon V.cond().     *    Row and column dimension (square matrix).     *    Internal symmetry flag.     *    Arrays for internal storage of eigenvalues.     *    Array for internal storage of eigenvectors.    *    Array for internal storage of nonsymmetric Hessenberg form.    *    Working storage for nonsymmetric algorithm.    *    Used for complex scalar division.     *    Symmetric Householder reduction to tridiagonal form.    private function tred2 () {        //  This is derived from the Algol procedures tred2 by        //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for        //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding        //  Fortran subroutine in EISPACK.        $this->d = $this->V[$this->n -1];        // Householder reduction to tridiagonal form.        for ($i = $this->n -1; $i > 0; --$i) {            // Scale to avoid under/overflow.                $this->e[$i] = $this->d[$i_];                for ($j = 0; $j < $i; ++$j) {                    $this->V[$j][$i] = $this->V[$i][$j] = 0.0;                // Generate Householder vector.                for ($k = 0; $k < $i; ++$k) {                    $h += pow($this->d[$k], 2);                $this->e[$i] = $scale * $g;                for ($j = 0; $j < $i; ++$j) {                // Apply similarity transformation to remaining columns.                for ($j = 0; $j < $i; ++$j) {                    $g = $this->e[$j] + $this->V[$j][$j] * $f;                    for ($k = $j +1; $k <= $i_; ++$k) {                        $g += $this->V[$k][$j] * $this->d[$k];                        $this->e[$k] += $this->V[$k][$j] * $f;                for ($j = 0; $j < $i; ++$j) {                    $f += $this->e[$j] * $this->d[$j];                for ($j=0; $j < $i; ++$j) {                    $this->e[$j] -= $hh * $this->d[$j];                for ($j = 0; $j < $i; ++$j) {                    for ($k = $j; $k <= $i_; ++$k) {                        $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]);                    $this->d[$j] = $this->V[$i -1][$j];        // Accumulate transformations.        for ($i = 0; $i < $this->n -1; ++$i) {            $this->V[$this->n-1][$i] = $this->V[$i][$i];                for ($k = 0; $k <= $i; ++$k) {                    $this->d[$k] = $this->V[$k][$i +1] / $h;                for ($j = 0; $j <= $i; ++$j) {                    for ($k = 0; $k <= $i; ++$k) {                        $g += $this->V[$k][$i +1] * $this->V[$k][$j];                    for ($k = 0; $k <= $i; ++$k) {                        $this->V[$k][$j] -= $g * $this->d[$k];            for ($k = 0; $k <= $i; ++$k) {                $this->V[$k][$i+1] = 0.0;        $this->d = $this->V[$this->n -1];        $this->V[$this->n-1][$this->n -1] = 1.0;     *    Symmetric tridiagonal QL algorithm.     *    This is derived from the Algol procedures tql2, by     *    Bowdler, Martin, Reinsch, and Wilkinson, Handbook for     *    Auto. Comp., Vol.ii-Linear Algebra, and the corresponding     *    Fortran subroutine in EISPACK.    private function tql2() {        for ($i = 1; $i < $this->n; ++$i) {            $this->e[$i-1] = $this->e[$i];        $this->e[$this->n-1] = 0.0;        for ($l = 0; $l < $this->n; ++$l) {            // Find small subdiagonal element            $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l]));                if (abs($this->e[$m]) <= $eps * $tst1)            // If m == l, $this->d[l] is an eigenvalue,                    // Could check iteration count here.                    // Compute implicit shift                    $p = ($this->d[$l +1] - $g) / (2.0 * $this->e[$l]);                    $this->d[$l] = $this->e[$l] / ($p + $r);                    $this->d[$l+1] = $this->e[$l] * ($p + $r);                    for ($i = $l + 2; $i < $this->n; ++$i)                    // Implicit QL transformation.                    for ($i = $m -1; $i >= $l; --$i) {                        $r  = hypo($p, $this->e[$i]);                        $this->e[$i+1] = $s * $r;                        $p = $c * $this->d[$i] - $s * $g;                        $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]);                        // Accumulate transformation.                        for ($k = 0; $k < $this->n; ++$k) {                            $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h;                            $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h;                    $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1;                // Check for convergence.                } while (abs($this->e[$l]) > $eps * $tst1);            $this->d[$l] = $this->d[$l] + $f;        // Sort eigenvalues and corresponding vectors.        for ($i = 0; $i < $this->n - 1; ++$i) {            for ($j = $i +1; $j < $this->n; ++$j) {                $this->d[$k] = $this->d[$i];                for ($j = 0; $j < $this->n; ++$j) {                    $this->V[$j][$i] = $this->V[$j][$k];     *    Nonsymmetric reduction to Hessenberg form.     *    This is derived from the Algol procedures orthes and ortran,     *    by Martin and Wilkinson, Handbook for Auto. Comp.,     *    Vol.ii-Linear Algebra, and the corresponding     *    Fortran subroutines in EISPACK.    private function orthes () {        for ($m = $low +1; $m <= $high -1; ++$m) {            for ($i = $m; $i <= $high; ++$i) {                $scale = $scale + abs($this->H[$i][$m -1]);                // Compute Householder transformation.                for ($i = $high; $i >= $m; --$i) {                    $this->ort[$i] = $this->H[$i][$m -1] / $scale;                    $h += $this->ort[$i] * $this->ort[$i];                if ($this->ort[$m] > 0) {                $h -= $this->ort[$m] * $g;                // Apply Householder similarity transformation                // H = (I -u * u' / h) * H * (I -u * u') / h)                for ($j = $m; $j < $this->n; ++$j) {                    for ($i = $high; $i >= $m; --$i) {                        $f += $this->ort[$i] * $this->H[$i][$j];                    for ($i = $m; $i <= $high; ++$i) {                        $this->H[$i][$j] -= $f * $this->ort[$i];                for ($i = 0; $i <= $high; ++$i) {                    for ($j = $high; $j >= $m; --$j) {                        $f += $this->ort[$j] * $this->H[$i][$j];                    for ($j = $m; $j <= $high; ++$j) {                        $this->H[$i][$j] -= $f * $this->ort[$j];                $this->ort[$m] = $scale * $this->ort[$m];                $this->H[$m][$m-1] = $scale * $g;        // Accumulate transformations (Algol's ortran).        for ($i = 0; $i < $this->n; ++$i) {            for ($j = 0; $j < $this->n; ++$j) {                $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0);        for ($m = $high -1; $m >= $low +1; --$m) {            if ($this->H[$m][$m-1] != 0.0) {                for ($i = $m +1; $i <= $high; ++$i) {                    $this->ort[$i] = $this->H[$i][$m -1];                for ($j = $m; $j <= $high; ++$j) {                    for ($i = $m; $i <= $high; ++$i) {                        $g += $this->ort[$i] * $this->V[$i][$j];                    // Double division avoids possible underflow                    $g = ($g / $this->ort[$m]) / $this->H[$m][$m -1];                    for ($i = $m; $i <= $high; ++$i) {                        $this->V[$i][$j] += $g * $this->ort[$i];     *    Performs complex division.    private function cdiv($xr, $xi, $yr, $yi) {            $this->cdivr = ($xr + $r * $xi) / $d;            $this->cdivi = ($xi - $r * $xr) / $d;            $this->cdivr = ($r * $xr + $xi) / $d;            $this->cdivi = ($r * $xi - $xr) / $d;     *    Nonsymmetric reduction from Hessenberg to real Schur form.     *    Code is derived from the Algol procedure hqr2,     *    by Martin and Wilkinson, Handbook for Auto. Comp.,     *    Vol.ii-Linear Algebra, and the corresponding     *    Fortran subroutine in EISPACK.    private function hqr2 () {        $p = $q = $r = $s = $z = 0;        // Store roots isolated by balanc and compute matrix norm        for ($i = 0; $i < $nn; ++$i) {            if (($i < $low) OR ($i > $high)) {                $this->d[$i] = $this->H[$i][$i];            for ($j = max($i -1, 0); $j < $nn; ++$j) {                $norm = $norm + abs($this->H[$i][$j]);        // Outer loop over eigenvalue index            // Look for single small sub-diagonal element                $s = abs($this->H[$l -1][$l -1]) + abs($this->H[$l][$l]);                if (abs($this->H[$l][$l-1]) < $eps * $s) {                $this->H[$n][$n] = $this->H[$n][$n] + $exshift;                $this->d[$n] = $this->H[$n][$n];                $w = $this->H[$n][$n -1] * $this->H[$n -1][$n];                $p = ($this->H[$n -1][$n -1] - $this->H[$n][$n]) / 2.0;                $this->H[$n][$n] = $this->H[$n][$n] + $exshift;                $this->H[$n-1][$n -1] = $this->H[$n -1][$n -1] + $exshift;                    $this->d[$n-1] = $x + $z;                    $this->d[$n] = $this->d[$n -1];                        $this->d[$n] = $x - $w / $z;                    $r = sqrt($p * $p + $q * $q);                    for ($j = $n -1; $j < $nn; ++$j) {                        $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j];                        $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z;                    for ($i = 0; $i <= n; ++$i) {                        $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n];                        $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z;                    // Accumulate transformations                    for ($i = $low; $i <= $high; ++$i) {                        $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n];                        $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z;                    $this->d[$n-1] = $x + $p;                    $y = $this->H[$n -1][$n -1];                    $w = $this->H[$n][$n -1] * $this->H[$n -1][$n];                // Wilkinson's original ad hoc shift                    for ($i = $low; $i <= $n; ++$i) {                    $s = abs($this->H[$n][$n -1]) + abs($this->H[$n -1][$n -2]);                // MATLAB's new ad hoc shift                        $s = $x - $w / (($y - $x) / 2.0 + $s);                        for ($i = $low; $i <= $n; ++$i) {                // Could check iteration count here.                // Look for two consecutive small sub-diagonal elements                    $p = ($r * $s - $w) / $this->H[$m +1][$m] + $this->H[$m][$m +1];                    $q = $this->H[$m +1][$m +1] - $z - $r - $s;                    $r = $this->H[$m +2][$m +1];                    if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) <                        $eps * (abs($p) * (abs($this->H[$m -1][$m -1]) + abs($z) + abs($this->H[$m +1][$m +1])))) {                for ($i = $m + 2; $i <= $n; ++$i) {                    $this->H[$i][$i-2] = 0.0;                        $this->H[$i][$i-3] = 0.0;                // Double QR step involving rows l:n and columns m:n                for ($k = $m; $k <= $n -1; ++$k) {                        $q = $this->H[$k +1][$k -1];                        $r = ($notlast ? $this->H[$k +2][$k -1] : 0.0);                    $s = sqrt($p * $p + $q * $q + $r * $r);                            $this->H[$k][$k-1] = -$s * $x;                            $this->H[$k][$k-1] = -$this->H[$k][$k -1];                        for ($j = $k; $j < $nn; ++$j) {                            $p = $this->H[$k][$j] + $q * $this->H[$k +1][$j];                                $p = $p + $r * $this->H[$k +2][$j];                                $this->H[$k+2][$j] = $this->H[$k +2][$j] - $p * $z;                            $this->H[$k][$j] = $this->H[$k][$j] - $p * $x;                            $this->H[$k+1][$j] = $this->H[$k +1][$j] - $p * $y;                        for ($i = 0; $i <= min($n, $k +3); ++$i) {                            $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k +1];                                $p = $p + $z * $this->H[$i][$k +2];                                $this->H[$i][$k+2] = $this->H[$i][$k +2] - $p * $r;                            $this->H[$i][$k] = $this->H[$i][$k] - $p;                            $this->H[$i][$k+1] = $this->H[$i][$k +1] - $p * $q;                        // Accumulate transformations                        for ($i = $low; $i <= $high; ++$i) {                            $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k +1];                                $p = $p + $z * $this->V[$i][$k +2];                                $this->V[$i][$k+2] = $this->V[$i][$k +2] - $p * $r;                            $this->V[$i][$k] = $this->V[$i][$k] - $p;                            $this->V[$i][$k+1] = $this->V[$i][$k +1] - $p * $q;        // Backsubstitute to find vectors of upper triangular form        for ($n = $nn -1; $n >= 0; --$n) {                for ($i = $n -1; $i >= 0; --$i) {                    $w = $this->H[$i][$i] - $p;                    for ($j = $l; $j <= $n; ++$j) {                        $r = $r + $this->H[$i][$j] * $this->H[$j][$n];                    if ($this->e[$i] < 0.0) {                        if ($this->e[$i] == 0.0) {                                $this->H[$i][$n] = -$r / $w;                                $this->H[$i][$n] = -$r / ($eps * $norm);                            $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i];                            $t = ($x * $s - $z * $r) / $q;                                $this->H[$i+1][$n] = ( -$r - $w * $t) / $x;                                $this->H[$i+1][$n] = ( -$s - $y * $t) / $z;                        $t = abs($this->H[$i][$n]);                        if (($eps * $t) * $t > 1) {                            for ($j = $i; $j <= $n; ++$j) {                                $this->H[$j][$n] = $this->H[$j][$n] / $t;                // Last vector component imaginary so matrix is triangular                if (abs($this->H[$n][$n-1]) > abs($this->H[$n -1][$n])) {                    $this->H[$n-1][$n -1] = $q / $this->H[$n][$n -1];                    $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n -1];                    $this->cdiv(0.0, -$this->H[$n -1][$n], $this->H[$n -1][$n -1] - $p, $q);                    $this->H[$n-1][$n -1] = $this->cdivr;                    $this->H[$n-1][$n] = $this->cdivi;                $this->H[$n][$n-1] = 0.0;                for ($i = $n -2; $i >= 0; --$i) {                    for ($j = $l; $j <= $n; ++$j) {                        $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n -1];                        $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];                    $w = $this->H[$i][$i] - $p;                    if ($this->e[$i] < 0.0) {                            $this->cdiv(-$ra, -$sa, $w, $q);                            $this->H[$i][$n-1] = $this->cdivr;                            $this->H[$i][$n]   = $this->cdivi;                            // Solve complex equations                            $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q;                            $vi = ($this->d[$i] - $p) * 2.0 * $q;                            if ($vr == 0.0 & $vi == 0.0) {                            $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi);                            $this->H[$i][$n-1] = $this->cdivr;                            $this->H[$i][$n]   = $this->cdivi;                                $this->H[$i+1][$n -1] = ( -$ra - $w * $this->H[$i][$n -1] + $q * $this->H[$i][$n]) / $x;                                $this->H[$i+1][$n] = ( -$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n -1]) / $x;                                $this->cdiv(-$r - $y * $this->H[$i][$n -1], -$s - $y * $this->H[$i][$n], $z, $q);                                $this->H[$i+1][$n -1] = $this->cdivr;                                $this->H[$i+1][$n] = $this->cdivi;                        $t = max(abs($this->H[$i][$n -1]),abs($this->H[$i][$n]));                        if (($eps * $t) * $t > 1) {                            for ($j = $i; $j <= $n; ++$j) {                                $this->H[$j][$n-1] = $this->H[$j][$n -1] / $t;                                $this->H[$j][$n]   = $this->H[$j][$n] / $t;            } // end else for complex case        // Vectors of isolated roots        for ($i = 0; $i < $nn; ++$i) {            if ($i < $low | $i > $high) {                for ($j = $i; $j < $nn; ++$j) {                    $this->V[$i][$j] = $this->H[$i][$j];        // Back transformation to get eigenvectors of original matrix        for ($j = $nn -1; $j >= $low; --$j) {            for ($i = $low; $i <= $high; ++$i) {                for ($k = $low; $k <= min($j,$high); ++$k) {                    $z = $z + $this->V[$i][$k] * $this->H[$k][$j];     *    Constructor: Check for symmetry, then construct the eigenvalue decomposition     *    @return Structure to access D and V.        $this->A = $Arg->getArray();        $this->n = $Arg->getColumnDimension();        for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) {            for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) {                $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]);            // Reduce to Hessenberg form.            // Reduce Hessenberg to real Schur form.     *    Return the eigenvector matrix        return new Matrix($this->V, $this->n, $this->n);     *    Return the real parts of the eigenvalues     *    Return the imaginary parts of the eigenvalues     *    Return the block diagonal eigenvalue matrix        for ($i = 0; $i < $this->n; ++$i) {            $D[$i][$i] = $this->d[$i];            $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;            $D[$i][$o] = $this->e[$i];}    //    class EigenvalueDecomposition |