Test Failed
Pull Request — master (#81)
by
unknown
04:16
created

EigenvalueDecomposition::getDiagonalEigenvalues()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 0
1
<?php declare(strict_types=1);
2
/**
3
 *
4
 *	Class to obtain eigenvalues and eigenvectors of a real matrix.
5
 *
6
 *	If A is symmetric, then A = V*D*V' where the eigenvalue matrix D
7
 *	is diagonal and the eigenvector matrix V is orthogonal (i.e.
8
 *	A = V.times(D.times(V.transpose())) and V.times(V.transpose())
9
 *	equals the identity matrix).
10
 *
11
 *	If A is not symmetric, then the eigenvalue matrix D is block diagonal
12
 *	with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
13
 *	lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda].  The
14
 *	columns of V represent the eigenvectors in the sense that A*V = V*D,
15
 *	i.e. A.times(V) equals V.times(D).  The matrix V may be badly
16
 *	conditioned, or even singular, so the validity of the equation
17
 *	A = V*D*inverse(V) depends upon V.cond().
18
 *
19
 *	@author  Paul Meagher
20
 *	@license PHP v3.0
21
 *	@version 1.1
22
 *
23
 *  Slightly changed to adapt the original code to PHP-ML library
24
 *  @date 2017/04/11
25
 *  @author Mustafa Karabulut
26
 */
27
28
namespace Phpml\Math\LinAlg;
29
30
use Phpml\Math\Matrix;
31
32
class EigenvalueDecomposition
33
{
34
35
    /**
36
     *	Row and column dimension (square matrix).
37
     *	@var int
38
     */
39
    private $n;
40
41
    /**
42
     *	Internal symmetry flag.
43
     *	@var int
44
     */
45
    private $issymmetric;
46
47
    /**
48
     *	Arrays for internal storage of eigenvalues.
49
     *	@var array
50
     */
51
    private $d = [];
52
    private $e = [];
53
54
    /**
55
     *	Array for internal storage of eigenvectors.
56
     *	@var array
57
     */
58
    private $V = [];
59
60
    /**
61
    *	Array for internal storage of nonsymmetric Hessenberg form.
62
    *	@var array
63
    */
64
    private $H = [];
65
66
    /**
67
    *	Working storage for nonsymmetric algorithm.
68
    *	@var array
69
    */
70
    private $ort;
71
72
    /**
73
    *	Used for complex scalar division.
74
    *	@var float
75
    */
76
    private $cdivr;
77
    private $cdivi;
78
79
80
    /**
81
     *	Symmetric Householder reduction to tridiagonal form.
82
     */
83
    private function tred2()
84
    {
85
        //  This is derived from the Algol procedures tred2 by
86
        //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
87
        //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
88
        //  Fortran subroutine in EISPACK.
89
        $this->d = $this->V[$this->n-1];
90
        // Householder reduction to tridiagonal form.
91
        for ($i = $this->n-1; $i > 0; --$i) {
92
            $i_ = $i -1;
93
            // Scale to avoid under/overflow.
94
            $h = $scale = 0.0;
95
            $scale += array_sum(array_map('abs', $this->d));
96
            if ($scale == 0.0) {
97
                $this->e[$i] = $this->d[$i_];
98
                $this->d = array_slice($this->V[$i_], 0, $i_);
99
                for ($j = 0; $j < $i; ++$j) {
100
                    $this->V[$j][$i] = $this->V[$i][$j] = 0.0;
101
                }
102
            } else {
103
                // Generate Householder vector.
104
                for ($k = 0; $k < $i; ++$k) {
105
                    $this->d[$k] /= $scale;
106
                    $h += pow($this->d[$k], 2);
107
                }
108
                $f = $this->d[$i_];
109
                $g = sqrt($h);
110
                if ($f > 0) {
111
                    $g = -$g;
112
                }
113
                $this->e[$i] = $scale * $g;
114
                $h = $h - $f * $g;
115
                $this->d[$i_] = $f - $g;
116
                for ($j = 0; $j < $i; ++$j) {
117
                    $this->e[$j] = 0.0;
118
                }
119
                // Apply similarity transformation to remaining columns.
120
                for ($j = 0; $j < $i; ++$j) {
121
                    $f = $this->d[$j];
122
                    $this->V[$j][$i] = $f;
123
                    $g = $this->e[$j] + $this->V[$j][$j] * $f;
124
                    for ($k = $j+1; $k <= $i_; ++$k) {
125
                        $g += $this->V[$k][$j] * $this->d[$k];
126
                        $this->e[$k] += $this->V[$k][$j] * $f;
127
                    }
128
                    $this->e[$j] = $g;
129
                }
130
                $f = 0.0;
131
                for ($j = 0; $j < $i; ++$j) {
132
                    if ($h === 0) {
133
                        $h = 1e-20;
134
                    }
135
                    $this->e[$j] /= $h;
136
                    $f += $this->e[$j] * $this->d[$j];
137
                }
138
                $hh = $f / (2 * $h);
139
                for ($j=0; $j < $i; ++$j) {
140
                    $this->e[$j] -= $hh * $this->d[$j];
141
                }
142
                for ($j = 0; $j < $i; ++$j) {
143
                    $f = $this->d[$j];
144
                    $g = $this->e[$j];
145
                    for ($k = $j; $k <= $i_; ++$k) {
146
                        $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]);
147
                    }
148
                    $this->d[$j] = $this->V[$i-1][$j];
149
                    $this->V[$i][$j] = 0.0;
150
                }
151
            }
152
            $this->d[$i] = $h;
153
        }
154
155
        // Accumulate transformations.
156
        for ($i = 0; $i < $this->n-1; ++$i) {
157
            $this->V[$this->n-1][$i] = $this->V[$i][$i];
158
            $this->V[$i][$i] = 1.0;
159
            $h = $this->d[$i+1];
160
            if ($h != 0.0) {
161 View Code Duplication
                for ($k = 0; $k <= $i; ++$k) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
                    $this->d[$k] = $this->V[$k][$i+1] / $h;
163
                }
164
                for ($j = 0; $j <= $i; ++$j) {
165
                    $g = 0.0;
166 View Code Duplication
                    for ($k = 0; $k <= $i; ++$k) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
167
                        $g += $this->V[$k][$i+1] * $this->V[$k][$j];
168
                    }
169 View Code Duplication
                    for ($k = 0; $k <= $i; ++$k) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
170
                        $this->V[$k][$j] -= $g * $this->d[$k];
171
                    }
172
                }
173
            }
174
            for ($k = 0; $k <= $i; ++$k) {
175
                $this->V[$k][$i+1] = 0.0;
176
            }
177
        }
178
179
        $this->d = $this->V[$this->n-1];
180
        $this->V[$this->n-1] = array_fill(0, $j, 0.0);
0 ignored issues
show
Bug introduced by
The variable $j does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
181
        $this->V[$this->n-1][$this->n-1] = 1.0;
182
        $this->e[0] = 0.0;
183
    }
184
185
186
    /**
187
     *	Symmetric tridiagonal QL algorithm.
188
     *
189
     *	This is derived from the Algol procedures tql2, by
190
     *	Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
191
     *	Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
192
     *	Fortran subroutine in EISPACK.
193
     */
194
    private function tql2()
195
    {
196
        for ($i = 1; $i < $this->n; ++$i) {
197
            $this->e[$i-1] = $this->e[$i];
198
        }
199
        $this->e[$this->n-1] = 0.0;
200
        $f = 0.0;
201
        $tst1 = 0.0;
202
        $eps  = pow(2.0, -52.0);
203
204
        for ($l = 0; $l < $this->n; ++$l) {
205
            // Find small subdiagonal element
206
            $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l]));
207
            $m = $l;
208
            while ($m < $this->n) {
209
                if (abs($this->e[$m]) <= $eps * $tst1) {
210
                    break;
211
                }
212
                ++$m;
213
            }
214
            // If m == l, $this->d[l] is an eigenvalue,
215
            // otherwise, iterate.
216
            if ($m > $l) {
217
                $iter = 0;
218
                do {
219
                    // Could check iteration count here.
220
                    $iter += 1;
221
                    // Compute implicit shift
222
                    $g = $this->d[$l];
223
                    $p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]);
224
                    $r = hypot($p, 1.0);
225
                    if ($p < 0) {
226
                        $r *= -1;
227
                    }
228
                    $this->d[$l] = $this->e[$l] / ($p + $r);
229
                    $this->d[$l+1] = $this->e[$l] * ($p + $r);
230
                    $dl1 = $this->d[$l+1];
231
                    $h = $g - $this->d[$l];
232
                    for ($i = $l + 2; $i < $this->n; ++$i) {
233
                        $this->d[$i] -= $h;
234
                    }
235
                    $f += $h;
236
                    // Implicit QL transformation.
237
                    $p = $this->d[$m];
238
                    $c = 1.0;
239
                    $c2 = $c3 = $c;
240
                    $el1 = $this->e[$l + 1];
241
                    $s = $s2 = 0.0;
242
                    for ($i = $m-1; $i >= $l; --$i) {
243
                        $c3 = $c2;
244
                        $c2 = $c;
245
                        $s2 = $s;
246
                        $g  = $c * $this->e[$i];
247
                        $h  = $c * $p;
248
                        $r  = hypot($p, $this->e[$i]);
249
                        $this->e[$i+1] = $s * $r;
250
                        $s = $this->e[$i] / $r;
251
                        $c = $p / $r;
252
                        $p = $c * $this->d[$i] - $s * $g;
253
                        $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]);
254
                        // Accumulate transformation.
255
                        for ($k = 0; $k < $this->n; ++$k) {
256
                            $h = $this->V[$k][$i+1];
257
                            $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h;
258
                            $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h;
259
                        }
260
                    }
261
                    $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1;
262
                    $this->e[$l] = $s * $p;
263
                    $this->d[$l] = $c * $p;
264
                // Check for convergence.
265
                } while (abs($this->e[$l]) > $eps * $tst1);
266
            }
267
            $this->d[$l] = $this->d[$l] + $f;
268
            $this->e[$l] = 0.0;
269
        }
270
271
        // Sort eigenvalues and corresponding vectors.
272
        for ($i = 0; $i < $this->n - 1; ++$i) {
273
            $k = $i;
274
            $p = $this->d[$i];
275
            for ($j = $i+1; $j < $this->n; ++$j) {
276
                if ($this->d[$j] < $p) {
277
                    $k = $j;
278
                    $p = $this->d[$j];
279
                }
280
            }
281
            if ($k != $i) {
282
                $this->d[$k] = $this->d[$i];
283
                $this->d[$i] = $p;
284
                for ($j = 0; $j < $this->n; ++$j) {
285
                    $p = $this->V[$j][$i];
286
                    $this->V[$j][$i] = $this->V[$j][$k];
287
                    $this->V[$j][$k] = $p;
288
                }
289
            }
290
        }
291
    }
292
293
294
    /**
295
     *	Nonsymmetric reduction to Hessenberg form.
296
     *
297
     *	This is derived from the Algol procedures orthes and ortran,
298
     *	by Martin and Wilkinson, Handbook for Auto. Comp.,
299
     *	Vol.ii-Linear Algebra, and the corresponding
300
     *	Fortran subroutines in EISPACK.
301
     */
302
    private function orthes()
303
    {
304
        $low  = 0;
305
        $high = $this->n-1;
306
307
        for ($m = $low+1; $m <= $high-1; ++$m) {
308
            // Scale column.
309
            $scale = 0.0;
310 View Code Duplication
            for ($i = $m; $i <= $high; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
                $scale = $scale + abs($this->H[$i][$m-1]);
312
            }
313
            if ($scale != 0.0) {
314
                // Compute Householder transformation.
315
                $h = 0.0;
316
                for ($i = $high; $i >= $m; --$i) {
317
                    $this->ort[$i] = $this->H[$i][$m-1] / $scale;
318
                    $h += $this->ort[$i] * $this->ort[$i];
319
                }
320
                $g = sqrt($h);
321
                if ($this->ort[$m] > 0) {
322
                    $g *= -1;
323
                }
324
                $h -= $this->ort[$m] * $g;
325
                $this->ort[$m] -= $g;
326
                // Apply Householder similarity transformation
327
                // H = (I -u * u' / h) * H * (I -u * u') / h)
328 View Code Duplication
                for ($j = $m; $j < $this->n; ++$j) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
329
                    $f = 0.0;
330
                    for ($i = $high; $i >= $m; --$i) {
331
                        $f += $this->ort[$i] * $this->H[$i][$j];
332
                    }
333
                    $f /= $h;
334
                    for ($i = $m; $i <= $high; ++$i) {
335
                        $this->H[$i][$j] -= $f * $this->ort[$i];
336
                    }
337
                }
338 View Code Duplication
                for ($i = 0; $i <= $high; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
339
                    $f = 0.0;
340
                    for ($j = $high; $j >= $m; --$j) {
341
                        $f += $this->ort[$j] * $this->H[$i][$j];
342
                    }
343
                    $f = $f / $h;
344
                    for ($j = $m; $j <= $high; ++$j) {
345
                        $this->H[$i][$j] -= $f * $this->ort[$j];
346
                    }
347
                }
348
                $this->ort[$m] = $scale * $this->ort[$m];
349
                $this->H[$m][$m-1] = $scale * $g;
350
            }
351
        }
352
353
        // Accumulate transformations (Algol's ortran).
354
        for ($i = 0; $i < $this->n; ++$i) {
355
            for ($j = 0; $j < $this->n; ++$j) {
356
                $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0);
357
            }
358
        }
359
        for ($m = $high-1; $m >= $low+1; --$m) {
360
            if ($this->H[$m][$m-1] != 0.0) {
361 View Code Duplication
                for ($i = $m+1; $i <= $high; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
362
                    $this->ort[$i] = $this->H[$i][$m-1];
363
                }
364
                for ($j = $m; $j <= $high; ++$j) {
365
                    $g = 0.0;
366
                    for ($i = $m; $i <= $high; ++$i) {
367
                        $g += $this->ort[$i] * $this->V[$i][$j];
368
                    }
369
                    // Double division avoids possible underflow
370
                    $g = ($g / $this->ort[$m]) / $this->H[$m][$m-1];
371
                    for ($i = $m; $i <= $high; ++$i) {
372
                        $this->V[$i][$j] += $g * $this->ort[$i];
373
                    }
374
                }
375
            }
376
        }
377
    }
378
379
380
    /**
381
     *	Performs complex division.
382
     */
383
    private function cdiv($xr, $xi, $yr, $yi)
384
    {
385
        if (abs($yr) > abs($yi)) {
386
            $r = $yi / $yr;
387
            $d = $yr + $r * $yi;
388
            $this->cdivr = ($xr + $r * $xi) / $d;
389
            $this->cdivi = ($xi - $r * $xr) / $d;
390
        } else {
391
            $r = $yr / $yi;
392
            $d = $yi + $r * $yr;
393
            $this->cdivr = ($r * $xr + $xi) / $d;
394
            $this->cdivi = ($r * $xi - $xr) / $d;
395
        }
396
    }
397
398
399
    /**
400
     *	Nonsymmetric reduction from Hessenberg to real Schur form.
401
     *
402
     *	Code is derived from the Algol procedure hqr2,
403
     *	by Martin and Wilkinson, Handbook for Auto. Comp.,
404
     *	Vol.ii-Linear Algebra, and the corresponding
405
     *	Fortran subroutine in EISPACK.
406
     */
407
    private function hqr2()
408
    {
409
        //  Initialize
410
        $nn = $this->n;
411
        $n  = $nn - 1;
412
        $low = 0;
413
        $high = $nn - 1;
414
        $eps = pow(2.0, -52.0);
415
        $exshift = 0.0;
416
        $p = $q = $r = $s = $z = 0;
417
        // Store roots isolated by balanc and compute matrix norm
418
        $norm = 0.0;
419
420
        for ($i = 0; $i < $nn; ++$i) {
421
            if (($i < $low) or ($i > $high)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
422
                $this->d[$i] = $this->H[$i][$i];
423
                $this->e[$i] = 0.0;
424
            }
425
            for ($j = max($i-1, 0); $j < $nn; ++$j) {
426
                $norm = $norm + abs($this->H[$i][$j]);
427
            }
428
        }
429
430
        // Outer loop over eigenvalue index
431
        $iter = 0;
432
        while ($n >= $low) {
433
            // Look for single small sub-diagonal element
434
            $l = $n;
435
            while ($l > $low) {
436
                $s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]);
437
                if ($s == 0.0) {
438
                    $s = $norm;
439
                }
440
                if (abs($this->H[$l][$l-1]) < $eps * $s) {
441
                    break;
442
                }
443
                --$l;
444
            }
445
            // Check for convergence
446
            // One root found
447
            if ($l == $n) {
448
                $this->H[$n][$n] = $this->H[$n][$n] + $exshift;
449
                $this->d[$n] = $this->H[$n][$n];
450
                $this->e[$n] = 0.0;
451
                --$n;
452
                $iter = 0;
453
            // Two roots found
454
            } elseif ($l == $n-1) {
455
                $w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
456
                $p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0;
457
                $q = $p * $p + $w;
458
                $z = sqrt(abs($q));
459
                $this->H[$n][$n] = $this->H[$n][$n] + $exshift;
460
                $this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift;
461
                $x = $this->H[$n][$n];
462
                // Real pair
463
                if ($q >= 0) {
464
                    if ($p >= 0) {
465
                        $z = $p + $z;
466
                    } else {
467
                        $z = $p - $z;
468
                    }
469
                    $this->d[$n-1] = $x + $z;
470
                    $this->d[$n] = $this->d[$n-1];
471
                    if ($z != 0.0) {
472
                        $this->d[$n] = $x - $w / $z;
473
                    }
474
                    $this->e[$n-1] = 0.0;
475
                    $this->e[$n] = 0.0;
476
                    $x = $this->H[$n][$n-1];
477
                    $s = abs($x) + abs($z);
478
                    $p = $x / $s;
479
                    $q = $z / $s;
480
                    $r = sqrt($p * $p + $q * $q);
481
                    $p = $p / $r;
482
                    $q = $q / $r;
483
                    // Row modification
484 View Code Duplication
                    for ($j = $n-1; $j < $nn; ++$j) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
485
                        $z = $this->H[$n-1][$j];
486
                        $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j];
487
                        $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z;
488
                    }
489
                    // Column modification
490 View Code Duplication
                    for ($i = 0; $i <= $n; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
491
                        $z = $this->H[$i][$n-1];
492
                        $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n];
493
                        $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z;
494
                    }
495
                    // Accumulate transformations
496 View Code Duplication
                    for ($i = $low; $i <= $high; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
497
                        $z = $this->V[$i][$n-1];
498
                        $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n];
499
                        $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z;
500
                    }
501
                // Complex pair
502
                } else {
503
                    $this->d[$n-1] = $x + $p;
504
                    $this->d[$n] = $x + $p;
505
                    $this->e[$n-1] = $z;
506
                    $this->e[$n] = -$z;
507
                }
508
                $n = $n - 2;
509
                $iter = 0;
510
            // No convergence yet
511
            } else {
512
                // Form shift
513
                $x = $this->H[$n][$n];
514
                $y = 0.0;
515
                $w = 0.0;
516
                if ($l < $n) {
517
                    $y = $this->H[$n-1][$n-1];
518
                    $w = $this->H[$n][$n-1] * $this->H[$n-1][$n];
519
                }
520
                // Wilkinson's original ad hoc shift
521
                if ($iter == 10) {
522
                    $exshift += $x;
523
                    for ($i = $low; $i <= $n; ++$i) {
524
                        $this->H[$i][$i] -= $x;
525
                    }
526
                    $s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]);
527
                    $x = $y = 0.75 * $s;
528
                    $w = -0.4375 * $s * $s;
529
                }
530
                // MATLAB's new ad hoc shift
531
                if ($iter == 30) {
532
                    $s = ($y - $x) / 2.0;
533
                    $s = $s * $s + $w;
534
                    if ($s > 0) {
535
                        $s = sqrt($s);
536
                        if ($y < $x) {
537
                            $s = -$s;
538
                        }
539
                        $s = $x - $w / (($y - $x) / 2.0 + $s);
540
                        for ($i = $low; $i <= $n; ++$i) {
541
                            $this->H[$i][$i] -= $s;
542
                        }
543
                        $exshift += $s;
544
                        $x = $y = $w = 0.964;
545
                    }
546
                }
547
                // Could check iteration count here.
548
                $iter = $iter + 1;
549
                // Look for two consecutive small sub-diagonal elements
550
                $m = $n - 2;
551
                while ($m >= $l) {
552
                    $z = $this->H[$m][$m];
553
                    $r = $x - $z;
554
                    $s = $y - $z;
555
                    $p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1];
556
                    $q = $this->H[$m+1][$m+1] - $z - $r - $s;
557
                    $r = $this->H[$m+2][$m+1];
558
                    $s = abs($p) + abs($q) + abs($r);
559
                    $p = $p / $s;
560
                    $q = $q / $s;
561
                    $r = $r / $s;
562
                    if ($m == $l) {
563
                        break;
564
                    }
565
                    if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) <
566
                        $eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) {
567
                        break;
568
                    }
569
                    --$m;
570
                }
571
                for ($i = $m + 2; $i <= $n; ++$i) {
572
                    $this->H[$i][$i-2] = 0.0;
573
                    if ($i > $m+2) {
574
                        $this->H[$i][$i-3] = 0.0;
575
                    }
576
                }
577
                // Double QR step involving rows l:n and columns m:n
578
                for ($k = $m; $k <= $n-1; ++$k) {
579
                    $notlast = ($k != $n-1);
580
                    if ($k != $m) {
581
                        $p = $this->H[$k][$k-1];
582
                        $q = $this->H[$k+1][$k-1];
583
                        $r = ($notlast ? $this->H[$k+2][$k-1] : 0.0);
584
                        $x = abs($p) + abs($q) + abs($r);
585
                        if ($x != 0.0) {
586
                            $p = $p / $x;
587
                            $q = $q / $x;
588
                            $r = $r / $x;
589
                        }
590
                    }
591
                    if ($x == 0.0) {
592
                        break;
593
                    }
594
                    $s = sqrt($p * $p + $q * $q + $r * $r);
595
                    if ($p < 0) {
596
                        $s = -$s;
597
                    }
598
                    if ($s != 0) {
599
                        if ($k != $m) {
600
                            $this->H[$k][$k-1] = -$s * $x;
601
                        } elseif ($l != $m) {
602
                            $this->H[$k][$k-1] = -$this->H[$k][$k-1];
603
                        }
604
                        $p = $p + $s;
605
                        $x = $p / $s;
606
                        $y = $q / $s;
607
                        $z = $r / $s;
608
                        $q = $q / $p;
609
                        $r = $r / $p;
610
                        // Row modification
611 View Code Duplication
                        for ($j = $k; $j < $nn; ++$j) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
612
                            $p = $this->H[$k][$j] + $q * $this->H[$k+1][$j];
613
                            if ($notlast) {
614
                                $p = $p + $r * $this->H[$k+2][$j];
615
                                $this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z;
616
                            }
617
                            $this->H[$k][$j] = $this->H[$k][$j] - $p * $x;
618
                            $this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y;
619
                        }
620
                        // Column modification
621 View Code Duplication
                        for ($i = 0; $i <= min($n, $k+3); ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
622
                            $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1];
623
                            if ($notlast) {
624
                                $p = $p + $z * $this->H[$i][$k+2];
625
                                $this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r;
626
                            }
627
                            $this->H[$i][$k] = $this->H[$i][$k] - $p;
628
                            $this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q;
629
                        }
630
                        // Accumulate transformations
631 View Code Duplication
                        for ($i = $low; $i <= $high; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
632
                            $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1];
633
                            if ($notlast) {
634
                                $p = $p + $z * $this->V[$i][$k+2];
635
                                $this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r;
636
                            }
637
                            $this->V[$i][$k] = $this->V[$i][$k] - $p;
638
                            $this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q;
639
                        }
640
                    }  // ($s != 0)
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
641
                }  // k loop
642
            }  // check convergence
643
        }  // while ($n >= $low)
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
644
645
        // Backsubstitute to find vectors of upper triangular form
646
        if ($norm == 0.0) {
647
            return;
648
        }
649
650
        for ($n = $nn-1; $n >= 0; --$n) {
651
            $p = $this->d[$n];
652
            $q = $this->e[$n];
653
            // Real vector
654
            if ($q == 0) {
655
                $l = $n;
656
                $this->H[$n][$n] = 1.0;
657
                for ($i = $n-1; $i >= 0; --$i) {
658
                    $w = $this->H[$i][$i] - $p;
659
                    $r = 0.0;
660
                    for ($j = $l; $j <= $n; ++$j) {
661
                        $r = $r + $this->H[$i][$j] * $this->H[$j][$n];
662
                    }
663
                    if ($this->e[$i] < 0.0) {
664
                        $z = $w;
665
                        $s = $r;
666
                    } else {
667
                        $l = $i;
668
                        if ($this->e[$i] == 0.0) {
669
                            if ($w != 0.0) {
670
                                $this->H[$i][$n] = -$r / $w;
671
                            } else {
672
                                $this->H[$i][$n] = -$r / ($eps * $norm);
673
                            }
674
                        // Solve real equations
675
                        } else {
676
                            $x = $this->H[$i][$i+1];
677
                            $y = $this->H[$i+1][$i];
678
                            $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i];
679
                            $t = ($x * $s - $z * $r) / $q;
680
                            $this->H[$i][$n] = $t;
681
                            if (abs($x) > abs($z)) {
682
                                $this->H[$i+1][$n] = (-$r - $w * $t) / $x;
683
                            } else {
684
                                $this->H[$i+1][$n] = (-$s - $y * $t) / $z;
685
                            }
686
                        }
687
                        // Overflow control
688
                        $t = abs($this->H[$i][$n]);
689
                        if (($eps * $t) * $t > 1) {
690 View Code Duplication
                            for ($j = $i; $j <= $n; ++$j) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
691
                                $this->H[$j][$n] = $this->H[$j][$n] / $t;
692
                            }
693
                        }
694
                    }
695
                }
696
            // Complex vector
697
            } elseif ($q < 0) {
698
                $l = $n-1;
699
                // Last vector component imaginary so matrix is triangular
700
                if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) {
701
                    $this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1];
702
                    $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1];
703
                } else {
704
                    $this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q);
705
                    $this->H[$n-1][$n-1] = $this->cdivr;
706
                    $this->H[$n-1][$n]   = $this->cdivi;
707
                }
708
                $this->H[$n][$n-1] = 0.0;
709
                $this->H[$n][$n] = 1.0;
710
                for ($i = $n-2; $i >= 0; --$i) {
711
                    // double ra,sa,vr,vi;
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
712
                    $ra = 0.0;
713
                    $sa = 0.0;
714
                    for ($j = $l; $j <= $n; ++$j) {
715
                        $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1];
716
                        $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];
717
                    }
718
                    $w = $this->H[$i][$i] - $p;
719
                    if ($this->e[$i] < 0.0) {
720
                        $z = $w;
721
                        $r = $ra;
722
                        $s = $sa;
723
                    } else {
724
                        $l = $i;
725
                        if ($this->e[$i] == 0) {
726
                            $this->cdiv(-$ra, -$sa, $w, $q);
727
                            $this->H[$i][$n-1] = $this->cdivr;
728
                            $this->H[$i][$n]   = $this->cdivi;
729
                        } else {
730
                            // Solve complex equations
731
                            $x = $this->H[$i][$i+1];
732
                            $y = $this->H[$i+1][$i];
733
                            $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q;
734
                            $vi = ($this->d[$i] - $p) * 2.0 * $q;
735
                            if ($vr == 0.0 & $vi == 0.0) {
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: ($vr == 0.0) & $vi == 0.0, Probably Intended Meaning: $vr == (0.0 & $vi == 0.0)

When comparing the result of a bit operation, we suggest to add explicit parenthesis and not to rely on PHP’s built-in operator precedence to ensure the code behaves as intended and to make it more readable.

Let’s take a look at these examples:

// Returns always int(0).
return 0 === $foo & 4;
return (0 === $foo) & 4;

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
736
                                $vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z));
737
                            }
738
                            $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi);
739
                            $this->H[$i][$n-1] = $this->cdivr;
740
                            $this->H[$i][$n]   = $this->cdivi;
741
                            if (abs($x) > (abs($z) + abs($q))) {
742
                                $this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x;
743
                                $this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x;
744
                            } else {
745
                                $this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q);
746
                                $this->H[$i+1][$n-1] = $this->cdivr;
747
                                $this->H[$i+1][$n]   = $this->cdivi;
748
                            }
749
                        }
750
                        // Overflow control
751
                        $t = max(abs($this->H[$i][$n-1]), abs($this->H[$i][$n]));
752
                        if (($eps * $t) * $t > 1) {
753
                            for ($j = $i; $j <= $n; ++$j) {
754
                                $this->H[$j][$n-1] = $this->H[$j][$n-1] / $t;
755
                                $this->H[$j][$n]   = $this->H[$j][$n] / $t;
756
                            }
757
                        }
758
                    } // end else
759
                } // end for
760
            } // end else for complex case
761
        } // end for
762
763
        // Vectors of isolated roots
764
        for ($i = 0; $i < $nn; ++$i) {
765
            if ($i < $low | $i > $high) {
766
                for ($j = $i; $j < $nn; ++$j) {
767
                    $this->V[$i][$j] = $this->H[$i][$j];
768
                }
769
            }
770
        }
771
772
        // Back transformation to get eigenvectors of original matrix
773
        for ($j = $nn-1; $j >= $low; --$j) {
774
            for ($i = $low; $i <= $high; ++$i) {
775
                $z = 0.0;
776
                for ($k = $low; $k <= min($j, $high); ++$k) {
777
                    $z = $z + $this->V[$i][$k] * $this->H[$k][$j];
778
                }
779
                $this->V[$i][$j] = $z;
780
            }
781
        }
782
    } // end hqr2
783
784
785
    /**
786
     *	Constructor: Check for symmetry, then construct the eigenvalue decomposition
787
     *
788
     * @param array $Arg
789
     */
790
    public function __construct(array $Arg)
791
    {
792
        $this->A = $Arg;
0 ignored issues
show
Bug introduced by
The property A does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
793
        $this->n = count($Arg[0]);
794
795
        $issymmetric = true;
796
        for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) {
797 View Code Duplication
            for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
798
                $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]);
799
            }
800
        }
801
802
        if ($issymmetric) {
803
            $this->V = $this->A;
804
            // Tridiagonalize.
805
            $this->tred2();
806
            // Diagonalize.
807
            $this->tql2();
808
        } else {
809
            $this->H = $this->A;
810
            $this->ort = [];
811
            // Reduce to Hessenberg form.
812
            $this->orthes();
813
            // Reduce Hessenberg to real Schur form.
814
            $this->hqr2();
815
        }
816
    }
817
818
    /**
819
     *	Return the eigenvector matrix
820
     *
821
     *	@access public
822
     *	@return array
823
     */
824
    public function getEigenvectors()
825
    {
826
        $vectors = $this->V;
827
828
        // Always return the eigenvectors of length 1.0
829
        $vectors = new Matrix($vectors);
830
        $vectors = array_map(function ($vect) {
831
            $sum = 0;
832 View Code Duplication
            for ($i=0; $i<count($vect); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
833
                $sum += $vect[$i] ** 2;
834
            }
835
            $sum = sqrt($sum);
836 View Code Duplication
            for ($i=0; $i<count($vect); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
837
                $vect[$i] /= $sum;
838
            }
839
            return $vect;
840
        }, $vectors->transpose()->toArray());
841
842
        // Re-index eigenvectors so that their indices will be the same with eigenvalues
843
        $vectors2 = [];
844
        foreach (array_keys($this->d) as $index) {
845
            $vectors2[$index] = $vectors[$index];
846
        }
847
848
        return $vectors2;
849
    }
850
851
852
    /**
853
     *	Return the real parts of the eigenvalues<br>
854
     *  d = real(diag(D));
855
     *
856
     *	@return array
857
     */
858
    public function getRealEigenvalues()
859
    {
860
        return $this->d;
861
    }
862
863
864
    /**
865
     *	Return the imaginary parts of the eigenvalues <br>
866
     *  d = imag(diag(D))
867
     *
868
     *	@return array
869
     */
870
    public function getImagEigenvalues()
871
    {
872
        return $this->e;
873
    }
874
875
876
    /**
877
     *	Return the block diagonal eigenvalue matrix
878
     *
879
     *	@return array
880
     */
881
    public function getDiagonalEigenvalues()
882
    {
883
        for ($i = 0; $i < $this->n; ++$i) {
884
            $D[$i] = array_fill(0, $this->n, 0.0);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$D was never initialized. Although not strictly required by PHP, it is generally a good practice to add $D = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
885
            $D[$i][$i] = $this->d[$i];
0 ignored issues
show
Bug introduced by
The variable $D does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
886
            if ($this->e[$i] == 0) {
887
                continue;
888
            }
889
            $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
890
            $D[$i][$o] = $this->e[$i];
891
        }
892
        return $D;
893
    }
894
}    //	class EigenvalueDecomposition
895