Completed
Push — develop ( 03f96a...8c66af )
by Adrien
19:36
created

Statistical::MAXIF()   C

Complexity

Conditions 7
Paths 14

Size

Total Lines 25
Code Lines 15

Duplication

Lines 25
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 15
nc 14
nop 3
dl 25
loc 25
rs 6.7272
c 0
b 0
f 0
ccs 0
cts 15
cp 0
crap 56
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation;
4
5
/* LOG_GAMMA_X_MAX_VALUE */
6 4
define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
7
8
/* XMININ */
9 4
define('XMININ', 2.23e-308);
10
11
/* EPS */
12 4
define('EPS', 2.22e-16);
13
14
/* SQRT2PI */
15 4
define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
16
17
/**
18
 * Copyright (c) 2006 - 2016 PhpSpreadsheet.
19
 *
20
 * This library is free software; you can redistribute it and/or
21
 * modify it under the terms of the GNU Lesser General Public
22
 * License as published by the Free Software Foundation; either
23
 * version 2.1 of the License, or (at your option) any later version.
24
 *
25
 * This library is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28
 * Lesser General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Lesser General Public
31
 * License along with this library; if not, write to the Free Software
32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33
 *
34
 * @category    PhpSpreadsheet
35
 *
36
 * @copyright   Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
37
 * @license     http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
38
 */
39
class Statistical
40
{
41
    private static function checkTrendArrays(&$array1, &$array2)
42
    {
43
        if (!is_array($array1)) {
44
            $array1 = [$array1];
45
        }
46
        if (!is_array($array2)) {
47
            $array2 = [$array2];
48
        }
49
50
        $array1 = Functions::flattenArray($array1);
51
        $array2 = Functions::flattenArray($array2);
52 View Code Duplication
        foreach ($array1 as $key => $value) {
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...
53
            if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
54
                unset($array1[$key], $array2[$key]);
55
            }
56
        }
57 View Code Duplication
        foreach ($array2 as $key => $value) {
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...
58
            if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
59
                unset($array1[$key], $array2[$key]);
60
            }
61
        }
62
        $array1 = array_merge($array1);
63
        $array2 = array_merge($array2);
64
65
        return true;
66
    }
67
68
    /**
69
     * Beta function.
70
     *
71
     * @author Jaco van Kooten
72
     *
73
     * @param p require p>0
74
     * @param q require q>0
75
     * @param mixed $p
76
     * @param mixed $q
77
     *
78
     * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
0 ignored issues
show
Documentation introduced by
The doc-type 0 could not be parsed: Unknown type name "0" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
79
     */
80
    private static function beta($p, $q)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
81
    {
82 View Code Duplication
        if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) {
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...
83
            return 0.0;
84
        }
85
86
        return exp(self::logBeta($p, $q));
87
    }
88
89
    /**
90
     * Incomplete beta function.
91
     *
92
     * @author Jaco van Kooten
93
     * @author Paul Meagher
94
     *
95
     * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
96
     *
97
     * @param x require 0<=x<=1
98
     * @param p require p>0
99
     * @param q require q>0
100
     * @param mixed $x
101
     * @param mixed $p
102
     * @param mixed $q
103
     *
104
     * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow
0 ignored issues
show
Documentation introduced by
The doc-type 0 could not be parsed: Unknown type name "0" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
105
     */
106
    private static function incompleteBeta($x, $p, $q)
107
    {
108
        if ($x <= 0.0) {
109
            return 0.0;
110
        } elseif ($x >= 1.0) {
111
            return 1.0;
112 View Code Duplication
        } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
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...
113
            return 0.0;
114
        }
115
        $beta_gam = exp((0 - self::logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x));
116
        if ($x < ($p + 1.0) / ($p + $q + 2.0)) {
117
            return $beta_gam * self::betaFraction($x, $p, $q) / $p;
118
        }
119
120
        return 1.0 - ($beta_gam * self::betaFraction(1 - $x, $q, $p) / $q);
121
    }
122
123
    // Function cache for logBeta function
124
    private static $logBetaCacheP = 0.0;
125
    private static $logBetaCacheQ = 0.0;
126
    private static $logBetaCacheResult = 0.0;
127
128
    /**
129
     * The natural logarithm of the beta function.
130
     *
131
     * @param p require p>0
132
     * @param q require q>0
133
     * @param mixed $p
134
     * @param mixed $q
135
     *
136
     * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
0 ignored issues
show
Documentation introduced by
The doc-type 0 could not be parsed: Unknown type name "0" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
137
     *
138
     * @author Jaco van Kooten
139
     */
140
    private static function logBeta($p, $q)
141
    {
142
        if ($p != self::$logBetaCacheP || $q != self::$logBetaCacheQ) {
143
            self::$logBetaCacheP = $p;
144
            self::$logBetaCacheQ = $q;
145
            if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
146
                self::$logBetaCacheResult = 0.0;
147
            } else {
148
                self::$logBetaCacheResult = self::logGamma($p) + self::logGamma($q) - self::logGamma($p + $q);
149
            }
150
        }
151
152
        return self::$logBetaCacheResult;
153
    }
154
155
    /**
156
     * Evaluates of continued fraction part of incomplete beta function.
157
     * Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
158
     *
159
     * @author Jaco van Kooten
160
     *
161
     * @param mixed $x
162
     * @param mixed $p
163
     * @param mixed $q
164
     */
165
    private static function betaFraction($x, $p, $q)
166
    {
167
        $c = 1.0;
168
        $sum_pq = $p + $q;
169
        $p_plus = $p + 1.0;
170
        $p_minus = $p - 1.0;
171
        $h = 1.0 - $sum_pq * $x / $p_plus;
172
        if (abs($h) < XMININ) {
173
            $h = XMININ;
174
        }
175
        $h = 1.0 / $h;
176
        $frac = $h;
177
        $m = 1;
178
        $delta = 0.0;
179
        while ($m <= MAX_ITERATIONS && abs($delta - 1.0) > PRECISION) {
180
            $m2 = 2 * $m;
181
            // even index for d
182
            $d = $m * ($q - $m) * $x / (($p_minus + $m2) * ($p + $m2));
183
            $h = 1.0 + $d * $h;
184
            if (abs($h) < XMININ) {
185
                $h = XMININ;
186
            }
187
            $h = 1.0 / $h;
188
            $c = 1.0 + $d / $c;
189
            if (abs($c) < XMININ) {
190
                $c = XMININ;
191
            }
192
            $frac *= $h * $c;
193
            // odd index for d
194
            $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2));
195
            $h = 1.0 + $d * $h;
196
            if (abs($h) < XMININ) {
197
                $h = XMININ;
198
            }
199
            $h = 1.0 / $h;
200
            $c = 1.0 + $d / $c;
201
            if (abs($c) < XMININ) {
202
                $c = XMININ;
203
            }
204
            $delta = $h * $c;
205
            $frac *= $delta;
206
            ++$m;
207
        }
208
209
        return $frac;
210
    }
211
212
    /**
213
     * logGamma function.
214
     *
215
     * @version 1.1
216
     *
217
     * @author Jaco van Kooten
218
     *
219
     * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher.
220
     *
221
     * The natural logarithm of the gamma function. <br />
222
     * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz <br />
223
     * Applied Mathematics Division <br />
224
     * Argonne National Laboratory <br />
225
     * Argonne, IL 60439 <br />
226
     * <p>
227
     * References:
228
     * <ol>
229
     * <li>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural
230
     *     Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.</li>
231
     * <li>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.</li>
232
     * <li>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.</li>
233
     * </ol>
234
     * </p>
235
     * <p>
236
     * From the original documentation:
237
     * </p>
238
     * <p>
239
     * This routine calculates the LOG(GAMMA) function for a positive real argument X.
240
     * Computation is based on an algorithm outlined in references 1 and 2.
241
     * The program uses rational functions that theoretically approximate LOG(GAMMA)
242
     * to at least 18 significant decimal digits. The approximation for X > 12 is from
243
     * reference 3, while approximations for X < 12.0 are similar to those in reference
244
     * 1, but are unpublished. The accuracy achieved depends on the arithmetic system,
245
     * the compiler, the intrinsic functions, and proper selection of the
246
     * machine-dependent constants.
247
     * </p>
248
     * <p>
249
     * Error returns: <br />
250
     * The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
251
     * The computation is believed to be free of underflow and overflow.
252
     * </p>
253
     *
254
     * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
255
     */
256
257
    // Function cache for logGamma
258
    private static $logGammaCacheResult = 0.0;
259
    private static $logGammaCacheX = 0.0;
260
261
    private static function logGamma($x)
262
    {
263
        // Log Gamma related constants
264
        static $lg_d1 = -0.5772156649015328605195174;
265
        static $lg_d2 = 0.4227843350984671393993777;
266
        static $lg_d4 = 1.791759469228055000094023;
267
268
        static $lg_p1 = [
269
            4.945235359296727046734888,
270
            201.8112620856775083915565,
271
            2290.838373831346393026739,
272
            11319.67205903380828685045,
273
            28557.24635671635335736389,
274
            38484.96228443793359990269,
275
            26377.48787624195437963534,
276
            7225.813979700288197698961,
277
        ];
278
        static $lg_p2 = [
279
            4.974607845568932035012064,
280
            542.4138599891070494101986,
281
            15506.93864978364947665077,
282
            184793.2904445632425417223,
283
            1088204.76946882876749847,
284
            3338152.967987029735917223,
285
            5106661.678927352456275255,
286
            3074109.054850539556250927,
287
        ];
288
        static $lg_p4 = [
289
            14745.02166059939948905062,
290
            2426813.369486704502836312,
291
            121475557.4045093227939592,
292
            2663432449.630976949898078,
293
            29403789566.34553899906876,
294
            170266573776.5398868392998,
295
            492612579337.743088758812,
296
            560625185622.3951465078242,
297
        ];
298
        static $lg_q1 = [
299
            67.48212550303777196073036,
300
            1113.332393857199323513008,
301
            7738.757056935398733233834,
302
            27639.87074403340708898585,
303
            54993.10206226157329794414,
304
            61611.22180066002127833352,
305
            36351.27591501940507276287,
306
            8785.536302431013170870835,
307
        ];
308
        static $lg_q2 = [
309
            183.0328399370592604055942,
310
            7765.049321445005871323047,
311
            133190.3827966074194402448,
312
            1136705.821321969608938755,
313
            5267964.117437946917577538,
314
            13467014.54311101692290052,
315
            17827365.30353274213975932,
316
            9533095.591844353613395747,
317
        ];
318
        static $lg_q4 = [
319
            2690.530175870899333379843,
320
            639388.5654300092398984238,
321
            41355999.30241388052042842,
322
            1120872109.61614794137657,
323
            14886137286.78813811542398,
324
            101680358627.2438228077304,
325
            341747634550.7377132798597,
326
            446315818741.9713286462081,
327
        ];
328
        static $lg_c = [
329
            -0.001910444077728,
330
            8.4171387781295e-4,
331
            -5.952379913043012e-4,
332
            7.93650793500350248e-4,
333
            -0.002777777777777681622553,
334
            0.08333333333333333331554247,
335
            0.0057083835261,
336
        ];
337
338
        // Rough estimate of the fourth root of logGamma_xBig
339
        static $lg_frtbig = 2.25e76;
340
        static $pnt68 = 0.6796875;
341
342
        if ($x == self::$logGammaCacheX) {
343
            return self::$logGammaCacheResult;
344
        }
345
        $y = $x;
346
        if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) {
347
            if ($y <= EPS) {
348
                $res = -log(y);
349
            } elseif ($y <= 1.5) {
350
                // ---------------------
351
                //    EPS .LT. X .LE. 1.5
352
                // ---------------------
353
                if ($y < $pnt68) {
354
                    $corr = -log($y);
355
                    $xm1 = $y;
356
                } else {
357
                    $corr = 0.0;
358
                    $xm1 = $y - 1.0;
359
                }
360
                if ($y <= 0.5 || $y >= $pnt68) {
361
                    $xden = 1.0;
362
                    $xnum = 0.0;
363
                    for ($i = 0; $i < 8; ++$i) {
364
                        $xnum = $xnum * $xm1 + $lg_p1[$i];
365
                        $xden = $xden * $xm1 + $lg_q1[$i];
366
                    }
367
                    $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden));
368 View Code Duplication
                } else {
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...
369
                    $xm2 = $y - 1.0;
370
                    $xden = 1.0;
371
                    $xnum = 0.0;
372
                    for ($i = 0; $i < 8; ++$i) {
373
                        $xnum = $xnum * $xm2 + $lg_p2[$i];
374
                        $xden = $xden * $xm2 + $lg_q2[$i];
375
                    }
376
                    $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
377
                }
378 View Code Duplication
            } elseif ($y <= 4.0) {
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...
379
                // ---------------------
380
                //    1.5 .LT. X .LE. 4.0
381
                // ---------------------
382
                $xm2 = $y - 2.0;
383
                $xden = 1.0;
384
                $xnum = 0.0;
385
                for ($i = 0; $i < 8; ++$i) {
386
                    $xnum = $xnum * $xm2 + $lg_p2[$i];
387
                    $xden = $xden * $xm2 + $lg_q2[$i];
388
                }
389
                $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
390
            } elseif ($y <= 12.0) {
391
                // ----------------------
392
                //    4.0 .LT. X .LE. 12.0
393
                // ----------------------
394
                $xm4 = $y - 4.0;
395
                $xden = -1.0;
396
                $xnum = 0.0;
397
                for ($i = 0; $i < 8; ++$i) {
398
                    $xnum = $xnum * $xm4 + $lg_p4[$i];
399
                    $xden = $xden * $xm4 + $lg_q4[$i];
400
                }
401
                $res = $lg_d4 + $xm4 * ($xnum / $xden);
402
            } else {
403
                // ---------------------------------
404
                //    Evaluate for argument .GE. 12.0
405
                // ---------------------------------
406
                $res = 0.0;
407
                if ($y <= $lg_frtbig) {
408
                    $res = $lg_c[6];
409
                    $ysq = $y * $y;
410
                    for ($i = 0; $i < 6; ++$i) {
411
                        $res = $res / $ysq + $lg_c[$i];
412
                    }
413
                    $res /= $y;
414
                    $corr = log($y);
415
                    $res = $res + log(SQRT2PI) - 0.5 * $corr;
416
                    $res += $y * ($corr - 1.0);
417
                }
418
            }
419
        } else {
420
            // --------------------------
421
            //    Return for bad arguments
422
            // --------------------------
423
            $res = MAX_VALUE;
424
        }
425
        // ------------------------------
426
        //    Final adjustments and return
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% 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...
427
        // ------------------------------
428
        self::$logGammaCacheX = $x;
429
        self::$logGammaCacheResult = $res;
430
431
        return $res;
432
    }
433
434
    //
435
    //    Private implementation of the incomplete Gamma function
436
    //
437
    private static function incompleteGamma($a, $x)
438
    {
439
        static $max = 32;
440
        $summer = 0;
441
        for ($n = 0; $n <= $max; ++$n) {
442
            $divisor = $a;
443
            for ($i = 1; $i <= $n; ++$i) {
444
                $divisor *= ($a + $i);
445
            }
446
            $summer += (pow($x, $n) / $divisor);
447
        }
448
449
        return pow($x, $a) * exp(0 - $x) * $summer;
450
    }
451
452
    //
453
    //    Private implementation of the Gamma function
454
    //
455
    private static function gamma($data)
456
    {
457
        if ($data == 0.0) {
458
            return 0;
459
        }
460
461
        static $p0 = 1.000000000190015;
462
        static $p = [
463
            1 => 76.18009172947146,
464
            2 => -86.50532032941677,
465
            3 => 24.01409824083091,
466
            4 => -1.231739572450155,
467
            5 => 1.208650973866179e-3,
468
            6 => -5.395239384953e-6,
469
        ];
470
471
        $y = $x = $data;
472
        $tmp = $x + 5.5;
473
        $tmp -= ($x + 0.5) * log($tmp);
474
475
        $summer = $p0;
476
        for ($j = 1; $j <= 6; ++$j) {
477
            $summer += ($p[$j] / ++$y);
478
        }
479
480
        return exp(0 - $tmp + log(SQRT2PI * $summer / $x));
481
    }
482
483
    /***************************************************************************
484
     *                                inverse_ncdf.php
485
     *                            -------------------
486
     *    begin                : Friday, January 16, 2004
487
     *    copyright            : (C) 2004 Michael Nickerson
488
     *    email                : [email protected]
489
     *
490
     ***************************************************************************/
491
    private static function inverseNcdf($p)
492
    {
493
        //    Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
494
        //    PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
495
        //    a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
496
        //    I have not checked the accuracy of this implementation. Be aware that PHP
497
        //    will truncate the coeficcients to 14 digits.
498
499
        //    You have permission to use and distribute this function freely for
500
        //    whatever purpose you want, but please show common courtesy and give credit
501
        //    where credit is due.
502
503
        //    Input paramater is $p - probability - where 0 < p < 1.
504
505
        //    Coefficients in rational approximations
506
        static $a = [
507
            1 => -3.969683028665376e+01,
508
            2 => 2.209460984245205e+02,
509
            3 => -2.759285104469687e+02,
510
            4 => 1.383577518672690e+02,
511
            5 => -3.066479806614716e+01,
512
            6 => 2.506628277459239e+00,
513
        ];
514
515
        static $b = [
516
            1 => -5.447609879822406e+01,
517
            2 => 1.615858368580409e+02,
518
            3 => -1.556989798598866e+02,
519
            4 => 6.680131188771972e+01,
520
            5 => -1.328068155288572e+01,
521
        ];
522
523
        static $c = [
524
            1 => -7.784894002430293e-03,
525
            2 => -3.223964580411365e-01,
526
            3 => -2.400758277161838e+00,
527
            4 => -2.549732539343734e+00,
528
            5 => 4.374664141464968e+00,
529
            6 => 2.938163982698783e+00,
530
        ];
531
532
        static $d = [
533
            1 => 7.784695709041462e-03,
534
            2 => 3.224671290700398e-01,
535
            3 => 2.445134137142996e+00,
536
            4 => 3.754408661907416e+00,
537
        ];
538
539
        //    Define lower and upper region break-points.
540
        $p_low = 0.02425; //Use lower region approx. below this
541
        $p_high = 1 - $p_low; //Use upper region approx. above this
542
543
        if (0 < $p && $p < $p_low) {
544
            //    Rational approximation for lower region.
545
            $q = sqrt(-2 * log($p));
546
547
            return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
548
                    (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
549
        } elseif ($p_low <= $p && $p <= $p_high) {
550
            //    Rational approximation for central region.
551
            $q = $p - 0.5;
552
            $r = $q * $q;
553
554
            return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q /
555
                   ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
556
        } elseif ($p_high < $p && $p < 1) {
557
            //    Rational approximation for upper region.
558
            $q = sqrt(-2 * log(1 - $p));
559
560
            return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
561
                     (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
562
        }
563
        //    If 0 < p < 1, return a null value
564
        return Functions::NULL();
565
    }
566
567
    private static function inverseNcdf2($prob)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
568
    {
569
        //    Approximation of inverse standard normal CDF developed by
570
        //    B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58.
0 ignored issues
show
Unused Code Comprehensibility introduced by
44% 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...
571
572
        $a1 = 2.50662823884;
573
        $a2 = -18.61500062529;
574
        $a3 = 41.39119773534;
575
        $a4 = -25.44106049637;
576
577
        $b1 = -8.4735109309;
578
        $b2 = 23.08336743743;
579
        $b3 = -21.06224101826;
580
        $b4 = 3.13082909833;
581
582
        $c1 = 0.337475482272615;
583
        $c2 = 0.976169019091719;
584
        $c3 = 0.160797971491821;
585
        $c4 = 2.76438810333863E-02;
586
        $c5 = 3.8405729373609E-03;
587
        $c6 = 3.951896511919E-04;
588
        $c7 = 3.21767881768E-05;
589
        $c8 = 2.888167364E-07;
590
        $c9 = 3.960315187E-07;
591
592
        $y = $prob - 0.5;
593
        if (abs($y) < 0.42) {
594
            $z = ($y * $y);
595
            $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1);
596
        } else {
597
            if ($y > 0) {
598
                $z = log(-log(1 - $prob));
599
            } else {
600
                $z = log(-log($prob));
601
            }
602
            $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9)))))));
603
            if ($y < 0) {
604
                $z = -$z;
605
            }
606
        }
607
608
        return $z;
609
    }
610
611
    //    function inverseNcdf2()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
612
613
    private static function inverseNcdf3($p)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
614
    {
615
        //    ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3.
616
        //    Produces the normal deviate Z corresponding to a given lower
617
        //    tail area of P; Z is accurate to about 1 part in 10**16.
618
        //
619
        //    This is a PHP version of the original FORTRAN code that can
620
        //    be found at http://lib.stat.cmu.edu/apstat/
621
        $split1 = 0.425;
0 ignored issues
show
Unused Code introduced by
$split1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
622
        $split2 = 5;
623
        $const1 = 0.180625;
624
        $const2 = 1.6;
625
626
        //    coefficients for p close to 0.5
627
        $a0 = 3.3871328727963666080;
628
        $a1 = 1.3314166789178437745E+2;
629
        $a2 = 1.9715909503065514427E+3;
630
        $a3 = 1.3731693765509461125E+4;
631
        $a4 = 4.5921953931549871457E+4;
632
        $a5 = 6.7265770927008700853E+4;
633
        $a6 = 3.3430575583588128105E+4;
634
        $a7 = 2.5090809287301226727E+3;
635
636
        $b1 = 4.2313330701600911252E+1;
637
        $b2 = 6.8718700749205790830E+2;
638
        $b3 = 5.3941960214247511077E+3;
639
        $b4 = 2.1213794301586595867E+4;
640
        $b5 = 3.9307895800092710610E+4;
641
        $b6 = 2.8729085735721942674E+4;
642
        $b7 = 5.2264952788528545610E+3;
643
644
        //    coefficients for p not close to 0, 0.5 or 1.
645
        $c0 = 1.42343711074968357734;
646
        $c1 = 4.63033784615654529590;
647
        $c2 = 5.76949722146069140550;
648
        $c3 = 3.64784832476320460504;
649
        $c4 = 1.27045825245236838258;
650
        $c5 = 2.41780725177450611770E-1;
651
        $c6 = 2.27238449892691845833E-2;
652
        $c7 = 7.74545014278341407640E-4;
653
654
        $d1 = 2.05319162663775882187;
655
        $d2 = 1.67638483018380384940;
656
        $d3 = 6.89767334985100004550E-1;
657
        $d4 = 1.48103976427480074590E-1;
658
        $d5 = 1.51986665636164571966E-2;
659
        $d6 = 5.47593808499534494600E-4;
660
        $d7 = 1.05075007164441684324E-9;
661
662
        //    coefficients for p near 0 or 1.
663
        $e0 = 6.65790464350110377720;
664
        $e1 = 5.46378491116411436990;
665
        $e2 = 1.78482653991729133580;
666
        $e3 = 2.96560571828504891230E-1;
667
        $e4 = 2.65321895265761230930E-2;
668
        $e5 = 1.24266094738807843860E-3;
669
        $e6 = 2.71155556874348757815E-5;
670
        $e7 = 2.01033439929228813265E-7;
671
672
        $f1 = 5.99832206555887937690E-1;
673
        $f2 = 1.36929880922735805310E-1;
674
        $f3 = 1.48753612908506148525E-2;
675
        $f4 = 7.86869131145613259100E-4;
676
        $f5 = 1.84631831751005468180E-5;
677
        $f6 = 1.42151175831644588870E-7;
678
        $f7 = 2.04426310338993978564E-15;
679
680
        $q = $p - 0.5;
681
682
        //    computation for p close to 0.5
683
        if (abs($q) <= split1) {
684
            $R = $const1 - $q * $q;
685
            $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) /
686
                      ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1);
687
        } else {
688
            if ($q < 0) {
689
                $R = $p;
690
            } else {
691
                $R = 1 - $p;
692
            }
693
            $R = pow(-log($R), 2);
694
695
            //    computation for p not close to 0, 0.5 or 1.
696
            if ($R <= $split2) {
697
                $R = $R - $const2;
698
                $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) /
699
                     ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1);
700
            } else {
701
                //    computation for p near 0 or 1.
702
                $R = $R - $split2;
703
                $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) /
704
                     ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1);
705
            }
706
            if ($q < 0) {
707
                $z = -$z;
708
            }
709
        }
710
711
        return $z;
712
    }
713
714
    /**
715
     * AVEDEV.
716
     *
717
     * Returns the average of the absolute deviations of data points from their mean.
718
     * AVEDEV is a measure of the variability in a data set.
719
     *
720
     * Excel Function:
721
     *        AVEDEV(value1[,value2[, ...]])
722
     *
723
     * @category Statistical Functions
724
     *
725
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
726
     *
727
     * @return    float
728
     */
729 View Code Duplication
    public static function AVEDEV()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
730
    {
731
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
732
733
        // Return value
734
        $returnValue = null;
735
736
        $aMean = self::AVERAGE($aArgs);
737
        if ($aMean != Functions::DIV0()) {
738
            $aCount = 0;
739
            foreach ($aArgs as $k => $arg) {
740
                if ((is_bool($arg)) &&
741
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
742
                    $arg = (int) $arg;
743
                }
744
                // Is it a numeric value?
745
                if ((is_numeric($arg)) && (!is_string($arg))) {
746
                    if (is_null($returnValue)) {
747
                        $returnValue = abs($arg - $aMean);
748
                    } else {
749
                        $returnValue += abs($arg - $aMean);
750
                    }
751
                    ++$aCount;
752
                }
753
            }
754
755
            // Return
756
            if ($aCount == 0) {
757
                return Functions::DIV0();
758
            }
759
760
            return $returnValue / $aCount;
761
        }
762
763
        return Functions::NAN();
764
    }
765
766
    /**
767
     * AVERAGE.
768
     *
769
     * Returns the average (arithmetic mean) of the arguments
770
     *
771
     * Excel Function:
772
     *        AVERAGE(value1[,value2[, ...]])
773
     *
774
     * @category Statistical Functions
775
     *
776
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
777
     *
778
     * @return    float
779
     */
780 2
    public static function AVERAGE()
781
    {
782 2
        $returnValue = $aCount = 0;
783
784
        // Loop through arguments
785 2
        foreach (Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
786 2
            if ((is_bool($arg)) &&
787 2
                ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
788
                $arg = (int) $arg;
789
            }
790
            // Is it a numeric value?
791 2
            if ((is_numeric($arg)) && (!is_string($arg))) {
792 2
                if (is_null($returnValue)) {
793
                    $returnValue = $arg;
794
                } else {
795 2
                    $returnValue += $arg;
796
                }
797 2
                ++$aCount;
798
            }
799
        }
800
801
        // Return
802 2
        if ($aCount > 0) {
803 2
            return $returnValue / $aCount;
804
        }
805
806
        return Functions::DIV0();
807
    }
808
809
    /**
810
     * AVERAGEA.
811
     *
812
     * Returns the average of its arguments, including numbers, text, and logical values
813
     *
814
     * Excel Function:
815
     *        AVERAGEA(value1[,value2[, ...]])
816
     *
817
     * @category Statistical Functions
818
     *
819
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
820
     *
821
     * @return    float
822
     */
823 1
    public static function AVERAGEA()
824
    {
825 1
        $returnValue = null;
826
827 1
        $aCount = 0;
828
        // Loop through arguments
829 1
        foreach (Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
830 1
            if ((is_bool($arg)) &&
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
831 1
                (!Functions::isMatrixValue($k))) {
832
            } else {
833 1
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
834 1
                    if (is_bool($arg)) {
835 1
                        $arg = (int) $arg;
836 1
                    } elseif (is_string($arg)) {
837 1
                        $arg = 0;
838
                    }
839 1
                    if (is_null($returnValue)) {
840 1
                        $returnValue = $arg;
841
                    } else {
842 1
                        $returnValue += $arg;
843
                    }
844 1
                    ++$aCount;
845
                }
846
            }
847
        }
848
849 1
        if ($aCount > 0) {
850 1
            return $returnValue / $aCount;
851
        }
852
853
        return Functions::DIV0();
854
    }
855
856
    /**
857
     * AVERAGEIF.
858
     *
859
     * Returns the average value from a range of cells that contain numbers within the list of arguments
860
     *
861
     * Excel Function:
862
     *        AVERAGEIF(value1[,value2[, ...]],condition)
863
     *
864
     * @category Mathematical and Trigonometric Functions
865
     *
866
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
867
     * @param    string        $condition        the criteria that defines which cells will be checked
868
     * @param    mixed[]        $averageArgs    Data values
869
     * @param mixed $aArgs
870
     *
871
     * @return    float
872
     */
873
    public static function AVERAGEIF($aArgs, $condition, $averageArgs = [])
874
    {
875
        $returnValue = 0;
876
877
        $aArgs = Functions::flattenArray($aArgs);
878
        $averageArgs = Functions::flattenArray($averageArgs);
879
        if (empty($averageArgs)) {
880
            $averageArgs = $aArgs;
0 ignored issues
show
Unused Code introduced by
$averageArgs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
881
        }
882
        $condition = Functions::ifCondition($condition);
883
        // Loop through arguments
884
        $aCount = 0;
885
        foreach ($aArgs as $key => $arg) {
886
            if (!is_numeric($arg)) {
887
                $arg = \PhpOffice\PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
888
            }
889
            $testCondition = '=' . $arg . $condition;
890
            if (\PhpOffice\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
891
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
892
                    $returnValue += $arg;
893
                    ++$aCount;
894
                }
895
            }
896
        }
897
898
        if ($aCount > 0) {
899
            return $returnValue / $aCount;
900
        }
901
902
        return Functions::DIV0();
903
    }
904
905
    /**
906
     * BETADIST.
907
     *
908
     * Returns the beta distribution.
909
     *
910
     * @param    float        $value            Value at which you want to evaluate the distribution
911
     * @param    float        $alpha            Parameter to the distribution
912
     * @param    float        $beta            Parameter to the distribution
913
     * @param mixed $rMin
914
     * @param mixed $rMax
915
     *
916
     * @return    float
917
     */
918
    public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1)
919
    {
920
        $value = Functions::flattenSingleValue($value);
921
        $alpha = Functions::flattenSingleValue($alpha);
922
        $beta = Functions::flattenSingleValue($beta);
923
        $rMin = Functions::flattenSingleValue($rMin);
924
        $rMax = Functions::flattenSingleValue($rMax);
925
926
        if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
927
            if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) {
928
                return Functions::NAN();
929
            }
930
            if ($rMin > $rMax) {
931
                $tmp = $rMin;
932
                $rMin = $rMax;
933
                $rMax = $tmp;
934
            }
935
            $value -= $rMin;
936
            $value /= ($rMax - $rMin);
937
938
            return self::incompleteBeta($value, $alpha, $beta);
0 ignored issues
show
Documentation introduced by
$value is of type integer|double, but the function expects a object<PhpOffice\PhpSpre...et\Calculation\require>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$alpha is of type integer|double|string, but the function expects a object<PhpOffice\PhpSpre...et\Calculation\require>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$beta is of type integer|double|string, but the function expects a object<PhpOffice\PhpSpre...et\Calculation\require>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
939
        }
940
941
        return Functions::VALUE();
942
    }
943
944
    /**
945
     * BETAINV.
946
     *
947
     * Returns the inverse of the beta distribution.
948
     *
949
     * @param    float        $probability    Probability at which you want to evaluate the distribution
950
     * @param    float        $alpha            Parameter to the distribution
951
     * @param    float        $beta            Parameter to the distribution
952
     * @param    float        $rMin            Minimum value
953
     * @param    float        $rMax            Maximum value
954
     *
955
     * @return    float
956
     */
957
    public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1)
958
    {
959
        $probability = Functions::flattenSingleValue($probability);
960
        $alpha = Functions::flattenSingleValue($alpha);
961
        $beta = Functions::flattenSingleValue($beta);
962
        $rMin = Functions::flattenSingleValue($rMin);
963
        $rMax = Functions::flattenSingleValue($rMax);
964
965
        if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
966 View Code Duplication
            if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) {
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...
967
                return Functions::NAN();
968
            }
969
            if ($rMin > $rMax) {
970
                $tmp = $rMin;
971
                $rMin = $rMax;
972
                $rMax = $tmp;
973
            }
974
            $a = 0;
975
            $b = 2;
976
977
            $i = 0;
978
            while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
979
                $guess = ($a + $b) / 2;
980
                $result = self::BETADIST($guess, $alpha, $beta);
981
                if (($result == $probability) || ($result == 0)) {
982
                    $b = $a;
983
                } elseif ($result > $probability) {
984
                    $b = $guess;
985
                } else {
986
                    $a = $guess;
987
                }
988
            }
989
            if ($i == MAX_ITERATIONS) {
990
                return Functions::NA();
991
            }
992
993
            return round($rMin + $guess * ($rMax - $rMin), 12);
0 ignored issues
show
Bug introduced by
The variable $guess 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...
994
        }
995
996
        return Functions::VALUE();
997
    }
998
999
    /**
1000
     * BINOMDIST.
1001
     *
1002
     * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
1003
     *        a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
1004
     *        when trials are independent, and when the probability of success is constant throughout the
1005
     *        experiment. For example, BINOMDIST can calculate the probability that two of the next three
1006
     *        babies born are male.
1007
     *
1008
     * @param    float        $value            Number of successes in trials
1009
     * @param    float        $trials            Number of trials
1010
     * @param    float        $probability    Probability of success on each trial
1011
     * @param    bool        $cumulative
1012
     *
1013
     * @return    float
1014
     *
1015
     * @todo    Cumulative distribution function
1016
     */
1017
    public static function BINOMDIST($value, $trials, $probability, $cumulative)
1018
    {
1019
        $value = floor(Functions::flattenSingleValue($value));
1020
        $trials = floor(Functions::flattenSingleValue($trials));
1021
        $probability = Functions::flattenSingleValue($probability);
1022
1023
        if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) {
1024
            if (($value < 0) || ($value > $trials)) {
1025
                return Functions::NAN();
1026
            }
1027
            if (($probability < 0) || ($probability > 1)) {
1028
                return Functions::NAN();
1029
            }
1030
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1031
                if ($cumulative) {
1032
                    $summer = 0;
1033
                    for ($i = 0; $i <= $value; ++$i) {
1034
                        $summer += MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i);
1035
                    }
1036
1037
                    return $summer;
1038
                }
1039
1040
                return MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value);
1041
            }
1042
        }
1043
1044
        return Functions::VALUE();
1045
    }
1046
1047
    /**
1048
     * CHIDIST.
1049
     *
1050
     * Returns the one-tailed probability of the chi-squared distribution.
1051
     *
1052
     * @param    float        $value            Value for the function
1053
     * @param    float        $degrees        degrees of freedom
1054
     *
1055
     * @return    float
1056
     */
1057
    public static function CHIDIST($value, $degrees)
1058
    {
1059
        $value = Functions::flattenSingleValue($value);
1060
        $degrees = floor(Functions::flattenSingleValue($degrees));
1061
1062
        if ((is_numeric($value)) && (is_numeric($degrees))) {
1063
            if ($degrees < 1) {
1064
                return Functions::NAN();
1065
            }
1066
            if ($value < 0) {
1067
                if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1068
                    return 1;
1069
                }
1070
1071
                return Functions::NAN();
1072
            }
1073
1074
            return 1 - (self::incompleteGamma($degrees / 2, $value / 2) / self::gamma($degrees / 2));
1075
        }
1076
1077
        return Functions::VALUE();
1078
    }
1079
1080
    /**
1081
     * CHIINV.
1082
     *
1083
     * Returns the one-tailed probability of the chi-squared distribution.
1084
     *
1085
     * @param    float        $probability    Probability for the function
1086
     * @param    float        $degrees        degrees of freedom
1087
     *
1088
     * @return    float
1089
     */
1090 View Code Duplication
    public static function CHIINV($probability, $degrees)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1091
    {
1092
        $probability = Functions::flattenSingleValue($probability);
1093
        $degrees = floor(Functions::flattenSingleValue($degrees));
1094
1095
        if ((is_numeric($probability)) && (is_numeric($degrees))) {
1096
            $xLo = 100;
1097
            $xHi = 0;
1098
1099
            $x = $xNew = 1;
1100
            $dx = 1;
1101
            $i = 0;
1102
1103
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1104
                // Apply Newton-Raphson step
1105
                $result = self::CHIDIST($x, $degrees);
1106
                $error = $result - $probability;
1107
                if ($error == 0.0) {
1108
                    $dx = 0;
1109
                } elseif ($error < 0.0) {
1110
                    $xLo = $x;
1111
                } else {
1112
                    $xHi = $x;
1113
                }
1114
                // Avoid division by zero
1115
                if ($result != 0.0) {
1116
                    $dx = $error / $result;
1117
                    $xNew = $x - $dx;
1118
                }
1119
                // If the NR fails to converge (which for example may be the
1120
                // case if the initial guess is too rough) we apply a bisection
1121
                // step to determine a more narrow interval around the root.
1122
                if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
1123
                    $xNew = ($xLo + $xHi) / 2;
1124
                    $dx = $xNew - $x;
1125
                }
1126
                $x = $xNew;
1127
            }
1128
            if ($i == MAX_ITERATIONS) {
1129
                return Functions::NA();
1130
            }
1131
1132
            return round($x, 12);
1133
        }
1134
1135
        return Functions::VALUE();
1136
    }
1137
1138
    /**
1139
     * CONFIDENCE.
1140
     *
1141
     * Returns the confidence interval for a population mean
1142
     *
1143
     * @param    float        $alpha
1144
     * @param    float        $stdDev        Standard Deviation
1145
     * @param    float        $size
1146
     *
1147
     * @return    float
1148
     */
1149
    public static function CONFIDENCE($alpha, $stdDev, $size)
1150
    {
1151
        $alpha = Functions::flattenSingleValue($alpha);
1152
        $stdDev = Functions::flattenSingleValue($stdDev);
1153
        $size = floor(Functions::flattenSingleValue($size));
1154
1155
        if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) {
1156
            if (($alpha <= 0) || ($alpha >= 1)) {
1157
                return Functions::NAN();
1158
            }
1159
            if (($stdDev <= 0) || ($size < 1)) {
1160
                return Functions::NAN();
1161
            }
1162
1163
            return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size);
1164
        }
1165
1166
        return Functions::VALUE();
1167
    }
1168
1169
    /**
1170
     * CORREL.
1171
     *
1172
     * Returns covariance, the average of the products of deviations for each data point pair.
1173
     *
1174
     * @param    array of mixed        Data Series Y
1175
     * @param    array of mixed        Data Series X
1176
     * @param mixed $yValues
1177
     * @param null|mixed $xValues
1178
     *
1179
     * @return    float
1180
     */
1181
    public static function CORREL($yValues, $xValues = null)
1182
    {
1183
        if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) {
1184
            return Functions::VALUE();
1185
        }
1186
        if (!self::checkTrendArrays($yValues, $xValues)) {
1187
            return Functions::VALUE();
1188
        }
1189
        $yValueCount = count($yValues);
1190
        $xValueCount = count($xValues);
1191
1192
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1193
            return Functions::NA();
1194
        } elseif ($yValueCount == 1) {
1195
            return Functions::DIV0();
1196
        }
1197
1198
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1199
1200
        return $bestFitLinear->getCorrelation();
1201
    }
1202
1203
    /**
1204
     * COUNT.
1205
     *
1206
     * Counts the number of cells that contain numbers within the list of arguments
1207
     *
1208
     * Excel Function:
1209
     *        COUNT(value1[,value2[, ...]])
1210
     *
1211
     * @category Statistical Functions
1212
     *
1213
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1214
     *
1215
     * @return    int
1216
     */
1217 2
    public static function COUNT()
1218
    {
1219 2
        $returnValue = 0;
1220
1221
        // Loop through arguments
1222 2
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1223 2
        foreach ($aArgs as $k => $arg) {
1224 2
            if ((is_bool($arg)) &&
1225 2
                ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
1226
                $arg = (int) $arg;
1227
            }
1228
            // Is it a numeric value?
1229 2
            if ((is_numeric($arg)) && (!is_string($arg))) {
1230 2
                ++$returnValue;
1231
            }
1232
        }
1233
1234 2
        return $returnValue;
1235
    }
1236
1237
    /**
1238
     * COUNTA.
1239
     *
1240
     * Counts the number of cells that are not empty within the list of arguments
1241
     *
1242
     * Excel Function:
1243
     *        COUNTA(value1[,value2[, ...]])
1244
     *
1245
     * @category Statistical Functions
1246
     *
1247
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1248
     *
1249
     * @return    int
1250
     */
1251 1 View Code Duplication
    public static function COUNTA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1252
    {
1253 1
        $returnValue = 0;
1254
1255
        // Loop through arguments
1256 1
        $aArgs = Functions::flattenArray(func_get_args());
1257 1
        foreach ($aArgs as $arg) {
1258
            // Is it a numeric, boolean or string value?
1259 1
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
1260 1
                ++$returnValue;
1261
            }
1262
        }
1263
1264 1
        return $returnValue;
1265
    }
1266
1267
    /**
1268
     * COUNTBLANK.
1269
     *
1270
     * Counts the number of empty cells within the list of arguments
1271
     *
1272
     * Excel Function:
1273
     *        COUNTBLANK(value1[,value2[, ...]])
1274
     *
1275
     * @category Statistical Functions
1276
     *
1277
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1278
     *
1279
     * @return    int
1280
     */
1281 View Code Duplication
    public static function COUNTBLANK()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1282
    {
1283
        $returnValue = 0;
1284
1285
        // Loop through arguments
1286
        $aArgs = Functions::flattenArray(func_get_args());
1287
        foreach ($aArgs as $arg) {
1288
            // Is it a blank cell?
1289
            if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
1290
                ++$returnValue;
1291
            }
1292
        }
1293
1294
        return $returnValue;
1295
    }
1296
1297
    /**
1298
     * COUNTIF.
1299
     *
1300
     * Counts the number of cells that contain numbers within the list of arguments
1301
     *
1302
     * Excel Function:
1303
     *        COUNTIF(value1[,value2[, ...]],condition)
1304
     *
1305
     * @category Statistical Functions
1306
     *
1307
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1308
     * @param    string        $condition        the criteria that defines which cells will be counted
1309
     * @param mixed $aArgs
1310
     *
1311
     * @return    int
1312
     */
1313
    public static function COUNTIF($aArgs, $condition)
1314
    {
1315
        $returnValue = 0;
1316
1317
        $aArgs = Functions::flattenArray($aArgs);
1318
        $condition = Functions::ifCondition($condition);
1319
        // Loop through arguments
1320
        foreach ($aArgs as $arg) {
1321
            if (!is_numeric($arg)) {
1322
                $arg = \PhpOffice\PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
1323
            }
1324
            $testCondition = '=' . $arg . $condition;
1325
            if (\PhpOffice\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1326
                // Is it a value within our criteria
1327
                ++$returnValue;
1328
            }
1329
        }
1330
1331
        return $returnValue;
1332
    }
1333
1334
    /**
1335
     * COVAR.
1336
     *
1337
     * Returns covariance, the average of the products of deviations for each data point pair.
1338
     *
1339
     * @param    array of mixed        Data Series Y
1340
     * @param    array of mixed        Data Series X
1341
     * @param mixed $yValues
1342
     * @param mixed $xValues
1343
     *
1344
     * @return    float
1345
     */
1346 View Code Duplication
    public static function COVAR($yValues, $xValues)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1347
    {
1348
        if (!self::checkTrendArrays($yValues, $xValues)) {
1349
            return Functions::VALUE();
1350
        }
1351
        $yValueCount = count($yValues);
1352
        $xValueCount = count($xValues);
1353
1354
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1355
            return Functions::NA();
1356
        } elseif ($yValueCount == 1) {
1357
            return Functions::DIV0();
1358
        }
1359
1360
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1361
1362
        return $bestFitLinear->getCovariance();
1363
    }
1364
1365
    /**
1366
     * CRITBINOM.
1367
     *
1368
     * Returns the smallest value for which the cumulative binomial distribution is greater
1369
     *        than or equal to a criterion value
1370
     *
1371
     * See http://support.microsoft.com/kb/828117/ for details of the algorithm used
1372
     *
1373
     * @param    float        $trials            number of Bernoulli trials
1374
     * @param    float        $probability    probability of a success on each trial
1375
     * @param    float        $alpha            criterion value
1376
     *
1377
     * @return    int
1378
     *
1379
     * @todo    Warning. This implementation differs from the algorithm detailed on the MS
1380
     *            web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess
1381
     *            This eliminates a potential endless loop error, but may have an adverse affect on the
1382
     *            accuracy of the function (although all my tests have so far returned correct results).
1383
     */
1384
    public static function CRITBINOM($trials, $probability, $alpha)
1385
    {
1386
        $trials = floor(Functions::flattenSingleValue($trials));
1387
        $probability = Functions::flattenSingleValue($probability);
1388
        $alpha = Functions::flattenSingleValue($alpha);
1389
1390
        if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) {
1391
            if ($trials < 0) {
1392
                return Functions::NAN();
1393
            } elseif (($probability < 0) || ($probability > 1)) {
1394
                return Functions::NAN();
1395
            } elseif (($alpha < 0) || ($alpha > 1)) {
1396
                return Functions::NAN();
1397
            } elseif ($alpha <= 0.5) {
1398
                $t = sqrt(log(1 / ($alpha * $alpha)));
1399
                $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t));
1400
            } else {
1401
                $t = sqrt(log(1 / pow(1 - $alpha, 2)));
1402
                $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t);
1403
            }
1404
            $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability)));
1405
            if ($Guess < 0) {
1406
                $Guess = 0;
1407
            } elseif ($Guess > $trials) {
1408
                $Guess = $trials;
1409
            }
1410
1411
            $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0;
1412
            $EssentiallyZero = 10e-12;
1413
1414
            $m = floor($trials * $probability);
1415
            ++$TotalUnscaledProbability;
1416
            if ($m == $Guess) {
1417
                ++$UnscaledPGuess;
1418
            }
1419
            if ($m <= $Guess) {
1420
                ++$UnscaledCumPGuess;
1421
            }
1422
1423
            $PreviousValue = 1;
1424
            $Done = false;
1425
            $k = $m + 1;
1426 View Code Duplication
            while ((!$Done) && ($k <= $trials)) {
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...
1427
                $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability));
1428
                $TotalUnscaledProbability += $CurrentValue;
1429
                if ($k == $Guess) {
1430
                    $UnscaledPGuess += $CurrentValue;
1431
                }
1432
                if ($k <= $Guess) {
1433
                    $UnscaledCumPGuess += $CurrentValue;
1434
                }
1435
                if ($CurrentValue <= $EssentiallyZero) {
1436
                    $Done = true;
1437
                }
1438
                $PreviousValue = $CurrentValue;
1439
                ++$k;
1440
            }
1441
1442
            $PreviousValue = 1;
1443
            $Done = false;
1444
            $k = $m - 1;
1445 View Code Duplication
            while ((!$Done) && ($k >= 0)) {
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...
1446
                $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability);
1447
                $TotalUnscaledProbability += $CurrentValue;
1448
                if ($k == $Guess) {
1449
                    $UnscaledPGuess += $CurrentValue;
1450
                }
1451
                if ($k <= $Guess) {
1452
                    $UnscaledCumPGuess += $CurrentValue;
1453
                }
1454
                if ($CurrentValue <= $EssentiallyZero) {
1455
                    $Done = true;
1456
                }
1457
                $PreviousValue = $CurrentValue;
1458
                --$k;
1459
            }
1460
1461
            $PGuess = $UnscaledPGuess / $TotalUnscaledProbability;
1462
            $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability;
1463
1464
            $CumPGuessMinus1 = $CumPGuess - 1;
1465
1466
            while (true) {
1467
                if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) {
1468
                    return $Guess;
1469
                } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) {
1470
                    $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability);
1471
                    $CumPGuessMinus1 = $CumPGuess;
1472
                    $CumPGuess = $CumPGuess + $PGuessPlus1;
1473
                    $PGuess = $PGuessPlus1;
1474
                    ++$Guess;
1475
                } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) {
1476
                    $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability;
1477
                    $CumPGuess = $CumPGuessMinus1;
1478
                    $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess;
1479
                    $PGuess = $PGuessMinus1;
1480
                    --$Guess;
1481
                }
1482
            }
1483
        }
1484
1485
        return Functions::VALUE();
1486
    }
1487
1488
    /**
1489
     * DEVSQ.
1490
     *
1491
     * Returns the sum of squares of deviations of data points from their sample mean.
1492
     *
1493
     * Excel Function:
1494
     *        DEVSQ(value1[,value2[, ...]])
1495
     *
1496
     * @category Statistical Functions
1497
     *
1498
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1499
     *
1500
     * @return    float
1501
     */
1502 1 View Code Duplication
    public static function DEVSQ()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1503
    {
1504 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1505
1506
        // Return value
1507 1
        $returnValue = null;
1508
1509 1
        $aMean = self::AVERAGE($aArgs);
1510 1
        if ($aMean != Functions::DIV0()) {
1511 1
            $aCount = -1;
1512 1
            foreach ($aArgs as $k => $arg) {
1513
                // Is it a numeric value?
1514 1
                if ((is_bool($arg)) &&
1515 1
                    ((!Functions::isCellValue($k)) ||
1516 1
                    (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
1517
                    $arg = (int) $arg;
1518
                }
1519 1
                if ((is_numeric($arg)) && (!is_string($arg))) {
1520 1
                    if (is_null($returnValue)) {
1521 1
                        $returnValue = pow(($arg - $aMean), 2);
1522
                    } else {
1523 1
                        $returnValue += pow(($arg - $aMean), 2);
1524
                    }
1525 1
                    ++$aCount;
1526
                }
1527
            }
1528
1529
            // Return
1530 1
            if (is_null($returnValue)) {
1531
                return Functions::NAN();
1532
            }
1533
1534 1
            return $returnValue;
1535
        }
1536
1537
        return self::NA();
0 ignored issues
show
Bug introduced by
The method NA() does not seem to exist on object<PhpOffice\PhpSpre...alculation\Statistical>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1538
    }
1539
1540
    /**
1541
     * EXPONDIST.
1542
     *
1543
     *    Returns the exponential distribution. Use EXPONDIST to model the time between events,
1544
     *        such as how long an automated bank teller takes to deliver cash. For example, you can
1545
     *        use EXPONDIST to determine the probability that the process takes at most 1 minute.
1546
     *
1547
     * @param    float        $value            Value of the function
1548
     * @param    float        $lambda            The parameter value
1549
     * @param    bool        $cumulative
1550
     *
1551
     * @return    float
1552
     */
1553
    public static function EXPONDIST($value, $lambda, $cumulative)
1554
    {
1555
        $value = Functions::flattenSingleValue($value);
1556
        $lambda = Functions::flattenSingleValue($lambda);
1557
        $cumulative = Functions::flattenSingleValue($cumulative);
1558
1559
        if ((is_numeric($value)) && (is_numeric($lambda))) {
1560
            if (($value < 0) || ($lambda < 0)) {
1561
                return Functions::NAN();
1562
            }
1563
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1564
                if ($cumulative) {
1565
                    return 1 - exp(0 - $value * $lambda);
1566
                }
1567
1568
                return $lambda * exp(0 - $value * $lambda);
1569
            }
1570
        }
1571
1572
        return Functions::VALUE();
1573
    }
1574
1575
    /**
1576
     * FISHER.
1577
     *
1578
     * Returns the Fisher transformation at x. This transformation produces a function that
1579
     *        is normally distributed rather than skewed. Use this function to perform hypothesis
1580
     *        testing on the correlation coefficient.
1581
     *
1582
     * @param    float        $value
1583
     *
1584
     * @return    float
1585
     */
1586
    public static function FISHER($value)
1587
    {
1588
        $value = Functions::flattenSingleValue($value);
1589
1590
        if (is_numeric($value)) {
1591
            if (($value <= -1) || ($value >= 1)) {
1592
                return Functions::NAN();
1593
            }
1594
1595
            return 0.5 * log((1 + $value) / (1 - $value));
1596
        }
1597
1598
        return Functions::VALUE();
1599
    }
1600
1601
    /**
1602
     * FISHERINV.
1603
     *
1604
     * Returns the inverse of the Fisher transformation. Use this transformation when
1605
     *        analyzing correlations between ranges or arrays of data. If y = FISHER(x), then
1606
     *        FISHERINV(y) = x.
1607
     *
1608
     * @param    float        $value
1609
     *
1610
     * @return    float
1611
     */
1612
    public static function FISHERINV($value)
1613
    {
1614
        $value = Functions::flattenSingleValue($value);
1615
1616
        if (is_numeric($value)) {
1617
            return (exp(2 * $value) - 1) / (exp(2 * $value) + 1);
1618
        }
1619
1620
        return Functions::VALUE();
1621
    }
1622
1623
    /**
1624
     * FORECAST.
1625
     *
1626
     * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
1627
     *
1628
     * @param    float                Value of X for which we want to find Y
1629
     * @param    array of mixed        Data Series Y
1630
     * @param    array of mixed        Data Series X
1631
     * @param mixed $xValue
1632
     * @param mixed $yValues
1633
     * @param mixed $xValues
1634
     *
1635
     * @return    float
1636
     */
1637
    public static function FORECAST($xValue, $yValues, $xValues)
1638
    {
1639
        $xValue = Functions::flattenSingleValue($xValue);
1640
        if (!is_numeric($xValue)) {
1641
            return Functions::VALUE();
1642
        } elseif (!self::checkTrendArrays($yValues, $xValues)) {
1643
            return Functions::VALUE();
1644
        }
1645
        $yValueCount = count($yValues);
1646
        $xValueCount = count($xValues);
1647
1648
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1649
            return Functions::NA();
1650
        } elseif ($yValueCount == 1) {
1651
            return Functions::DIV0();
1652
        }
1653
1654
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1655
1656
        return $bestFitLinear->getValueOfYForX($xValue);
1657
    }
1658
1659
    /**
1660
     * GAMMADIST.
1661
     *
1662
     * Returns the gamma distribution.
1663
     *
1664
     * @param    float        $value            Value at which you want to evaluate the distribution
1665
     * @param    float        $a                Parameter to the distribution
1666
     * @param    float        $b                Parameter to the distribution
1667
     * @param    bool        $cumulative
1668
     *
1669
     * @return    float
1670
     */
1671
    public static function GAMMADIST($value, $a, $b, $cumulative)
1672
    {
1673
        $value = Functions::flattenSingleValue($value);
1674
        $a = Functions::flattenSingleValue($a);
1675
        $b = Functions::flattenSingleValue($b);
1676
1677
        if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) {
1678
            if (($value < 0) || ($a <= 0) || ($b <= 0)) {
1679
                return Functions::NAN();
1680
            }
1681
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1682
                if ($cumulative) {
1683
                    return self::incompleteGamma($a, $value / $b) / self::gamma($a);
1684
                }
1685
1686
                return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a - 1) * exp(0 - ($value / $b));
1687
            }
1688
        }
1689
1690
        return Functions::VALUE();
1691
    }
1692
1693
    /**
1694
     * GAMMAINV.
1695
     *
1696
     * Returns the inverse of the beta distribution.
1697
     *
1698
     * @param    float        $probability    Probability at which you want to evaluate the distribution
1699
     * @param    float        $alpha            Parameter to the distribution
1700
     * @param    float        $beta            Parameter to the distribution
1701
     *
1702
     * @return    float
1703
     */
1704
    public static function GAMMAINV($probability, $alpha, $beta)
1705
    {
1706
        $probability = Functions::flattenSingleValue($probability);
1707
        $alpha = Functions::flattenSingleValue($alpha);
1708
        $beta = Functions::flattenSingleValue($beta);
1709
1710
        if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) {
1711 View Code Duplication
            if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) {
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...
1712
                return Functions::NAN();
1713
            }
1714
1715
            $xLo = 0;
1716
            $xHi = $alpha * $beta * 5;
1717
1718
            $x = $xNew = 1;
1719
            $error = $pdf = 0;
0 ignored issues
show
Unused Code introduced by
$pdf is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Unused Code introduced by
$error is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1720
            $dx = 1024;
1721
            $i = 0;
1722
1723
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1724
                // Apply Newton-Raphson step
1725
                $error = self::GAMMADIST($x, $alpha, $beta, true) - $probability;
1726
                if ($error < 0.0) {
1727
                    $xLo = $x;
1728
                } else {
1729
                    $xHi = $x;
1730
                }
1731
                $pdf = self::GAMMADIST($x, $alpha, $beta, false);
1732
                // Avoid division by zero
1733
                if ($pdf != 0.0) {
1734
                    $dx = $error / $pdf;
1735
                    $xNew = $x - $dx;
1736
                }
1737
                // If the NR fails to converge (which for example may be the
1738
                // case if the initial guess is too rough) we apply a bisection
1739
                // step to determine a more narrow interval around the root.
1740
                if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) {
1741
                    $xNew = ($xLo + $xHi) / 2;
1742
                    $dx = $xNew - $x;
1743
                }
1744
                $x = $xNew;
1745
            }
1746
            if ($i == MAX_ITERATIONS) {
1747
                return Functions::NA();
1748
            }
1749
1750
            return $x;
1751
        }
1752
1753
        return Functions::VALUE();
1754
    }
1755
1756
    /**
1757
     * GAMMALN.
1758
     *
1759
     * Returns the natural logarithm of the gamma function.
1760
     *
1761
     * @param    float        $value
1762
     *
1763
     * @return    float
1764
     */
1765 View Code Duplication
    public static function GAMMALN($value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1766
    {
1767
        $value = Functions::flattenSingleValue($value);
1768
1769
        if (is_numeric($value)) {
1770
            if ($value <= 0) {
1771
                return Functions::NAN();
1772
            }
1773
1774
            return log(self::gamma($value));
1775
        }
1776
1777
        return Functions::VALUE();
1778
    }
1779
1780
    /**
1781
     * GEOMEAN.
1782
     *
1783
     * Returns the geometric mean of an array or range of positive data. For example, you
1784
     *        can use GEOMEAN to calculate average growth rate given compound interest with
1785
     *        variable rates.
1786
     *
1787
     * Excel Function:
1788
     *        GEOMEAN(value1[,value2[, ...]])
1789
     *
1790
     * @category Statistical Functions
1791
     *
1792
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1793
     *
1794
     * @return    float
1795
     */
1796
    public static function GEOMEAN()
1797
    {
1798
        $aArgs = Functions::flattenArray(func_get_args());
1799
1800
        $aMean = MathTrig::PRODUCT($aArgs);
1801
        if (is_numeric($aMean) && ($aMean > 0)) {
1802
            $aCount = self::COUNT($aArgs);
1803
            if (self::MIN($aArgs) > 0) {
1804
                return pow($aMean, (1 / $aCount));
1805
            }
1806
        }
1807
1808
        return Functions::NAN();
1809
    }
1810
1811
    /**
1812
     * GROWTH.
1813
     *
1814
     * Returns values along a predicted emponential Trend
1815
     *
1816
     * @param    array of mixed        Data Series Y
1817
     * @param    array of mixed        Data Series X
1818
     * @param    array of mixed        Values of X for which we want to find Y
1819
     * @param    bool                a logical value specifying whether to force the intersect to equal 0
1820
     * @param mixed $yValues
1821
     * @param mixed $xValues
1822
     * @param mixed $newValues
1823
     * @param mixed $const
1824
     *
1825
     * @return    array of float
1826
     */
1827 View Code Duplication
    public static function GROWTH($yValues, $xValues = [], $newValues = [], $const = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1828
    {
1829
        $yValues = Functions::flattenArray($yValues);
1830
        $xValues = Functions::flattenArray($xValues);
1831
        $newValues = Functions::flattenArray($newValues);
1832
        $const = (is_null($const)) ? true : (bool) Functions::flattenSingleValue($const);
1833
1834
        $bestFitExponential = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_EXPONENTIAL, $yValues, $xValues, $const);
1835
        if (empty($newValues)) {
1836
            $newValues = $bestFitExponential->getXValues();
1837
        }
1838
1839
        $returnArray = [];
1840
        foreach ($newValues as $xValue) {
1841
            $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
1842
        }
1843
1844
        return $returnArray;
1845
    }
1846
1847
    /**
1848
     * HARMEAN.
1849
     *
1850
     * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
1851
     *        arithmetic mean of reciprocals.
1852
     *
1853
     * Excel Function:
1854
     *        HARMEAN(value1[,value2[, ...]])
1855
     *
1856
     * @category Statistical Functions
1857
     *
1858
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1859
     *
1860
     * @return    float
1861
     */
1862
    public static function HARMEAN()
1863
    {
1864
        // Return value
1865
        $returnValue = Functions::NA();
1866
1867
        // Loop through arguments
1868
        $aArgs = Functions::flattenArray(func_get_args());
1869
        if (self::MIN($aArgs) < 0) {
1870
            return Functions::NAN();
1871
        }
1872
        $aCount = 0;
1873
        foreach ($aArgs as $arg) {
1874
            // Is it a numeric value?
1875
            if ((is_numeric($arg)) && (!is_string($arg))) {
1876
                if ($arg <= 0) {
1877
                    return Functions::NAN();
1878
                }
1879
                if (is_null($returnValue)) {
1880
                    $returnValue = (1 / $arg);
1881
                } else {
1882
                    $returnValue += (1 / $arg);
1883
                }
1884
                ++$aCount;
1885
            }
1886
        }
1887
1888
        // Return
1889
        if ($aCount > 0) {
1890
            return 1 / ($returnValue / $aCount);
1891
        }
1892
1893
        return $returnValue;
1894
    }
1895
1896
    /**
1897
     * HYPGEOMDIST.
1898
     *
1899
     * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of
1900
     * sample successes, given the sample size, population successes, and population size.
1901
     *
1902
     * @param    float        $sampleSuccesses        Number of successes in the sample
1903
     * @param    float        $sampleNumber            Size of the sample
1904
     * @param    float        $populationSuccesses    Number of successes in the population
1905
     * @param    float        $populationNumber        Population size
1906
     *
1907
     * @return    float
1908
     */
1909
    public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
1910
    {
1911
        $sampleSuccesses = floor(Functions::flattenSingleValue($sampleSuccesses));
1912
        $sampleNumber = floor(Functions::flattenSingleValue($sampleNumber));
1913
        $populationSuccesses = floor(Functions::flattenSingleValue($populationSuccesses));
1914
        $populationNumber = floor(Functions::flattenSingleValue($populationNumber));
1915
1916
        if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
1917
            if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
1918
                return Functions::NAN();
1919
            }
1920
            if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) {
1921
                return Functions::NAN();
1922
            }
1923
            if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) {
1924
                return Functions::NAN();
1925
            }
1926
1927
            return MathTrig::COMBIN($populationSuccesses, $sampleSuccesses) *
1928
                   MathTrig::COMBIN($populationNumber - $populationSuccesses, $sampleNumber - $sampleSuccesses) /
1929
                   MathTrig::COMBIN($populationNumber, $sampleNumber);
1930
        }
1931
1932
        return Functions::VALUE();
1933
    }
1934
1935
    /**
1936
     * INTERCEPT.
1937
     *
1938
     * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
1939
     *
1940
     * @param    array of mixed        Data Series Y
1941
     * @param    array of mixed        Data Series X
1942
     * @param mixed $yValues
1943
     * @param mixed $xValues
1944
     *
1945
     * @return    float
1946
     */
1947 View Code Duplication
    public static function INTERCEPT($yValues, $xValues)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
1948
    {
1949
        if (!self::checkTrendArrays($yValues, $xValues)) {
1950
            return Functions::VALUE();
1951
        }
1952
        $yValueCount = count($yValues);
1953
        $xValueCount = count($xValues);
1954
1955
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1956
            return Functions::NA();
1957
        } elseif ($yValueCount == 1) {
1958
            return Functions::DIV0();
1959
        }
1960
1961
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1962
1963
        return $bestFitLinear->getIntersect();
1964
    }
1965
1966
    /**
1967
     * KURT.
1968
     *
1969
     * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
1970
     * or flatness of a distribution compared with the normal distribution. Positive
1971
     * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
1972
     * relatively flat distribution.
1973
     *
1974
     * @param    array    Data Series
1975
     *
1976
     * @return    float
1977
     */
1978
    public static function KURT()
1979
    {
1980
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1981
        $mean = self::AVERAGE($aArgs);
1982
        $stdDev = self::STDEV($aArgs);
1983
1984
        if ($stdDev > 0) {
1985
            $count = $summer = 0;
1986
            // Loop through arguments
1987 View Code Duplication
            foreach ($aArgs as $k => $arg) {
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...
1988
                if ((is_bool($arg)) &&
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1989
                    (!Functions::isMatrixValue($k))) {
1990
                } else {
1991
                    // Is it a numeric value?
1992
                    if ((is_numeric($arg)) && (!is_string($arg))) {
1993
                        $summer += pow((($arg - $mean) / $stdDev), 4);
1994
                        ++$count;
1995
                    }
1996
                }
1997
            }
1998
1999
            // Return
2000
            if ($count > 3) {
2001
                return $summer * ($count * ($count + 1) / (($count - 1) * ($count - 2) * ($count - 3))) - (3 * pow($count - 1, 2) / (($count - 2) * ($count - 3)));
2002
            }
2003
        }
2004
2005
        return Functions::DIV0();
2006
    }
2007
2008
    /**
2009
     * LARGE.
2010
     *
2011
     * Returns the nth largest value in a data set. You can use this function to
2012
     *        select a value based on its relative standing.
2013
     *
2014
     * Excel Function:
2015
     *        LARGE(value1[,value2[, ...]],entry)
2016
     *
2017
     * @category Statistical Functions
2018
     *
2019
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2020
     * @param    int            $entry            Position (ordered from the largest) in the array or range of data to return
0 ignored issues
show
Bug introduced by
There is no parameter named $entry. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2021
     *
2022
     * @return    float
2023
     */
2024 View Code Duplication
    public static function LARGE()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2025
    {
2026
        $aArgs = Functions::flattenArray(func_get_args());
2027
2028
        // Calculate
2029
        $entry = floor(array_pop($aArgs));
2030
2031
        if ((is_numeric($entry)) && (!is_string($entry))) {
2032
            $mArgs = [];
2033
            foreach ($aArgs as $arg) {
2034
                // Is it a numeric value?
2035
                if ((is_numeric($arg)) && (!is_string($arg))) {
2036
                    $mArgs[] = $arg;
2037
                }
2038
            }
2039
            $count = self::COUNT($mArgs);
2040
            $entry = floor(--$entry);
2041
            if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
2042
                return Functions::NAN();
2043
            }
2044
            rsort($mArgs);
2045
2046
            return $mArgs[$entry];
2047
        }
2048
2049
        return Functions::VALUE();
2050
    }
2051
2052
    /**
2053
     * LINEST.
2054
     *
2055
     * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
2056
     *        and then returns an array that describes the line.
2057
     *
2058
     * @param    array of mixed        Data Series Y
2059
     * @param    array of mixed        Data Series X
2060
     * @param    bool                a logical value specifying whether to force the intersect to equal 0
2061
     * @param    bool                a logical value specifying whether to return additional regression statistics
2062
     * @param mixed $yValues
2063
     * @param null|mixed $xValues
2064
     * @param mixed $const
2065
     * @param mixed $stats
2066
     *
2067
     * @return    array
2068
     */
2069
    public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
2070
    {
2071
        $const = (is_null($const)) ? true : (bool) Functions::flattenSingleValue($const);
2072
        $stats = (is_null($stats)) ? false : (bool) Functions::flattenSingleValue($stats);
2073
        if (is_null($xValues)) {
2074
            $xValues = range(1, count(Functions::flattenArray($yValues)));
2075
        }
2076
2077
        if (!self::checkTrendArrays($yValues, $xValues)) {
2078
            return Functions::VALUE();
2079
        }
2080
        $yValueCount = count($yValues);
2081
        $xValueCount = count($xValues);
2082
2083
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2084
            return Functions::NA();
2085
        } elseif ($yValueCount == 1) {
2086
            return 0;
2087
        }
2088
2089
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues, $const);
2090 View Code Duplication
        if ($stats) {
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...
2091
            return [
2092
                [
2093
                    $bestFitLinear->getSlope(),
2094
                    $bestFitLinear->getSlopeSE(),
2095
                    $bestFitLinear->getGoodnessOfFit(),
2096
                    $bestFitLinear->getF(),
2097
                    $bestFitLinear->getSSRegression(),
2098
                ],
2099
                [
2100
                    $bestFitLinear->getIntersect(),
2101
                    $bestFitLinear->getIntersectSE(),
2102
                    $bestFitLinear->getStdevOfResiduals(),
2103
                    $bestFitLinear->getDFResiduals(),
2104
                    $bestFitLinear->getSSResiduals(),
2105
                ],
2106
            ];
2107
        }
2108
2109
        return [
2110
                $bestFitLinear->getSlope(),
2111
                $bestFitLinear->getIntersect(),
2112
            ];
2113
    }
2114
2115
    /**
2116
     * LOGEST.
2117
     *
2118
     * Calculates an exponential curve that best fits the X and Y data series,
2119
     *        and then returns an array that describes the line.
2120
     *
2121
     * @param    array of mixed        Data Series Y
2122
     * @param    array of mixed        Data Series X
2123
     * @param    bool                a logical value specifying whether to force the intersect to equal 0
2124
     * @param    bool                a logical value specifying whether to return additional regression statistics
2125
     * @param mixed $yValues
2126
     * @param null|mixed $xValues
2127
     * @param mixed $const
2128
     * @param mixed $stats
2129
     *
2130
     * @return    array
2131
     */
2132
    public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false)
2133
    {
2134
        $const = (is_null($const)) ? true : (bool) Functions::flattenSingleValue($const);
2135
        $stats = (is_null($stats)) ? false : (bool) Functions::flattenSingleValue($stats);
2136
        if (is_null($xValues)) {
2137
            $xValues = range(1, count(Functions::flattenArray($yValues)));
2138
        }
2139
2140
        if (!self::checkTrendArrays($yValues, $xValues)) {
2141
            return Functions::VALUE();
2142
        }
2143
        $yValueCount = count($yValues);
2144
        $xValueCount = count($xValues);
2145
2146
        foreach ($yValues as $value) {
2147
            if ($value <= 0.0) {
2148
                return Functions::NAN();
2149
            }
2150
        }
2151
2152
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2153
            return Functions::NA();
2154
        } elseif ($yValueCount == 1) {
2155
            return 1;
2156
        }
2157
2158
        $bestFitExponential = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_EXPONENTIAL, $yValues, $xValues, $const);
2159 View Code Duplication
        if ($stats) {
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...
2160
            return [
2161
                [
2162
                    $bestFitExponential->getSlope(),
2163
                    $bestFitExponential->getSlopeSE(),
2164
                    $bestFitExponential->getGoodnessOfFit(),
2165
                    $bestFitExponential->getF(),
2166
                    $bestFitExponential->getSSRegression(),
2167
                ],
2168
                [
2169
                    $bestFitExponential->getIntersect(),
2170
                    $bestFitExponential->getIntersectSE(),
2171
                    $bestFitExponential->getStdevOfResiduals(),
2172
                    $bestFitExponential->getDFResiduals(),
2173
                    $bestFitExponential->getSSResiduals(),
2174
                ],
2175
            ];
2176
        }
2177
2178
        return [
2179
                $bestFitExponential->getSlope(),
2180
                $bestFitExponential->getIntersect(),
2181
            ];
2182
    }
2183
2184
    /**
2185
     * LOGINV.
2186
     *
2187
     * Returns the inverse of the normal cumulative distribution
2188
     *
2189
     * @param    float        $probability
2190
     * @param    float        $mean
2191
     * @param    float        $stdDev
2192
     *
2193
     * @return    float
2194
     *
2195
     * @todo    Try implementing P J Acklam's refinement algorithm for greater
2196
     *            accuracy if I can get my head round the mathematics
2197
     *            (as described at) http://home.online.no/~pjacklam/notes/invnorm/
2198
     */
2199 View Code Duplication
    public static function LOGINV($probability, $mean, $stdDev)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2200
    {
2201
        $probability = Functions::flattenSingleValue($probability);
2202
        $mean = Functions::flattenSingleValue($mean);
2203
        $stdDev = Functions::flattenSingleValue($stdDev);
2204
2205
        if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2206
            if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) {
2207
                return Functions::NAN();
2208
            }
2209
2210
            return exp($mean + $stdDev * self::NORMSINV($probability));
2211
        }
2212
2213
        return Functions::VALUE();
2214
    }
2215
2216
    /**
2217
     * LOGNORMDIST.
2218
     *
2219
     * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed
2220
     * with parameters mean and standard_dev.
2221
     *
2222
     * @param    float        $value
2223
     * @param    float        $mean
2224
     * @param    float        $stdDev
2225
     *
2226
     * @return    float
2227
     */
2228
    public static function LOGNORMDIST($value, $mean, $stdDev)
2229
    {
2230
        $value = Functions::flattenSingleValue($value);
2231
        $mean = Functions::flattenSingleValue($mean);
2232
        $stdDev = Functions::flattenSingleValue($stdDev);
2233
2234
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2235
            if (($value <= 0) || ($stdDev <= 0)) {
2236
                return Functions::NAN();
2237
            }
2238
2239
            return self::NORMSDIST((log($value) - $mean) / $stdDev);
2240
        }
2241
2242
        return Functions::VALUE();
2243
    }
2244
2245
    /**
2246
     * MAX.
2247
     *
2248
     * MAX returns the value of the element of the values passed that has the highest value,
2249
     *        with negative numbers considered smaller than positive numbers.
2250
     *
2251
     * Excel Function:
2252
     *        MAX(value1[,value2[, ...]])
2253
     *
2254
     * @category Statistical Functions
2255
     *
2256
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2257
     *
2258
     * @return    float
2259
     */
2260 2 View Code Duplication
    public static function MAX()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2261
    {
2262 2
        $returnValue = null;
2263
2264
        // Loop through arguments
2265 2
        $aArgs = Functions::flattenArray(func_get_args());
2266 2
        foreach ($aArgs as $arg) {
2267
            // Is it a numeric value?
2268 2
            if ((is_numeric($arg)) && (!is_string($arg))) {
2269 2
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2270 2
                    $returnValue = $arg;
2271
                }
2272
            }
2273
        }
2274
2275 2
        if (is_null($returnValue)) {
2276
            return 0;
2277
        }
2278
2279 2
        return $returnValue;
2280
    }
2281
2282
    /**
2283
     * MAXA.
2284
     *
2285
     * Returns the greatest value in a list of arguments, including numbers, text, and logical values
2286
     *
2287
     * Excel Function:
2288
     *        MAXA(value1[,value2[, ...]])
2289
     *
2290
     * @category Statistical Functions
2291
     *
2292
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2293
     *
2294
     * @return    float
2295
     */
2296 1 View Code Duplication
    public static function MAXA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2297
    {
2298 1
        $returnValue = null;
2299
2300
        // Loop through arguments
2301 1
        $aArgs = Functions::flattenArray(func_get_args());
2302 1
        foreach ($aArgs as $arg) {
2303
            // Is it a numeric value?
2304 1
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2305 1
                if (is_bool($arg)) {
2306 1
                    $arg = (int) $arg;
2307 1
                } elseif (is_string($arg)) {
2308 1
                    $arg = 0;
2309
                }
2310 1
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2311 1
                    $returnValue = $arg;
2312
                }
2313
            }
2314
        }
2315
2316 1
        if (is_null($returnValue)) {
2317
            return 0;
2318
        }
2319
2320 1
        return $returnValue;
2321
    }
2322
2323
    /**
2324
     * MAXIF.
2325
     *
2326
     * Counts the maximum value within a range of cells that contain numbers within the list of arguments
2327
     *
2328
     * Excel Function:
2329
     *        MAXIF(value1[,value2[, ...]],condition)
2330
     *
2331
     * @category Mathematical and Trigonometric Functions
2332
     *
2333
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2334
     * @param    string        $condition        the criteria that defines which cells will be checked
2335
     * @param mixed $aArgs
2336
     * @param mixed $sumArgs
2337
     *
2338
     * @return    float
2339
     */
2340 View Code Duplication
    public static function MAXIF($aArgs, $condition, $sumArgs = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2341
    {
2342
        $returnValue = null;
2343
2344
        $aArgs = Functions::flattenArray($aArgs);
2345
        $sumArgs = Functions::flattenArray($sumArgs);
2346
        if (empty($sumArgs)) {
2347
            $sumArgs = $aArgs;
0 ignored issues
show
Unused Code introduced by
$sumArgs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2348
        }
2349
        $condition = Functions::ifCondition($condition);
2350
        // Loop through arguments
2351
        foreach ($aArgs as $key => $arg) {
2352
            if (!is_numeric($arg)) {
2353
                $arg = \PhpOffice\PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
2354
            }
2355
            $testCondition = '=' . $arg . $condition;
2356
            if (\PhpOffice\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2357
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2358
                    $returnValue = $arg;
2359
                }
2360
            }
2361
        }
2362
2363
        return $returnValue;
2364
    }
2365
2366
    /**
2367
     * MEDIAN.
2368
     *
2369
     * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
2370
     *
2371
     * Excel Function:
2372
     *        MEDIAN(value1[,value2[, ...]])
2373
     *
2374
     * @category Statistical Functions
2375
     *
2376
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2377
     *
2378
     * @return    float
2379
     */
2380 1
    public static function MEDIAN()
2381
    {
2382 1
        $returnValue = Functions::NAN();
2383
2384 1
        $mArgs = [];
2385
        // Loop through arguments
2386 1
        $aArgs = Functions::flattenArray(func_get_args());
2387 1
        foreach ($aArgs as $arg) {
2388
            // Is it a numeric value?
2389 1
            if ((is_numeric($arg)) && (!is_string($arg))) {
2390 1
                $mArgs[] = $arg;
2391
            }
2392
        }
2393
2394 1
        $mValueCount = count($mArgs);
2395 1
        if ($mValueCount > 0) {
2396 1
            sort($mArgs, SORT_NUMERIC);
2397 1
            $mValueCount = $mValueCount / 2;
2398 1
            if ($mValueCount == floor($mValueCount)) {
2399 1
                $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
2400
            } else {
2401 1
                $mValueCount = floor($mValueCount);
2402 1
                $returnValue = $mArgs[$mValueCount];
2403
            }
2404
        }
2405
2406 1
        return $returnValue;
2407
    }
2408
2409
    /**
2410
     * MIN.
2411
     *
2412
     * MIN returns the value of the element of the values passed that has the smallest value,
2413
     *        with negative numbers considered smaller than positive numbers.
2414
     *
2415
     * Excel Function:
2416
     *        MIN(value1[,value2[, ...]])
2417
     *
2418
     * @category Statistical Functions
2419
     *
2420
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2421
     *
2422
     * @return    float
2423
     */
2424 2 View Code Duplication
    public static function MIN()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2425
    {
2426 2
        $returnValue = null;
2427
2428
        // Loop through arguments
2429 2
        $aArgs = Functions::flattenArray(func_get_args());
2430 2
        foreach ($aArgs as $arg) {
2431
            // Is it a numeric value?
2432 2
            if ((is_numeric($arg)) && (!is_string($arg))) {
2433 2
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2434 2
                    $returnValue = $arg;
2435
                }
2436
            }
2437
        }
2438
2439 2
        if (is_null($returnValue)) {
2440
            return 0;
2441
        }
2442
2443 2
        return $returnValue;
2444
    }
2445
2446
    /**
2447
     * MINA.
2448
     *
2449
     * Returns the smallest value in a list of arguments, including numbers, text, and logical values
2450
     *
2451
     * Excel Function:
2452
     *        MINA(value1[,value2[, ...]])
2453
     *
2454
     * @category Statistical Functions
2455
     *
2456
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2457
     *
2458
     * @return    float
2459
     */
2460 1 View Code Duplication
    public static function MINA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2461
    {
2462 1
        $returnValue = null;
2463
2464
        // Loop through arguments
2465 1
        $aArgs = Functions::flattenArray(func_get_args());
2466 1
        foreach ($aArgs as $arg) {
2467
            // Is it a numeric value?
2468 1
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2469 1
                if (is_bool($arg)) {
2470 1
                    $arg = (int) $arg;
2471 1
                } elseif (is_string($arg)) {
2472 1
                    $arg = 0;
2473
                }
2474 1
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2475 1
                    $returnValue = $arg;
2476
                }
2477
            }
2478
        }
2479
2480 1
        if (is_null($returnValue)) {
2481
            return 0;
2482
        }
2483
2484 1
        return $returnValue;
2485
    }
2486
2487
    /**
2488
     * MINIF.
2489
     *
2490
     * Returns the minimum value within a range of cells that contain numbers within the list of arguments
2491
     *
2492
     * Excel Function:
2493
     *        MINIF(value1[,value2[, ...]],condition)
2494
     *
2495
     * @category Mathematical and Trigonometric Functions
2496
     *
2497
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2498
     * @param    string        $condition        the criteria that defines which cells will be checked
2499
     * @param mixed $aArgs
2500
     * @param mixed $sumArgs
2501
     *
2502
     * @return    float
2503
     */
2504 View Code Duplication
    public static function MINIF($aArgs, $condition, $sumArgs = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2505
    {
2506
        $returnValue = null;
2507
2508
        $aArgs = Functions::flattenArray($aArgs);
2509
        $sumArgs = Functions::flattenArray($sumArgs);
2510
        if (empty($sumArgs)) {
2511
            $sumArgs = $aArgs;
0 ignored issues
show
Unused Code introduced by
$sumArgs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2512
        }
2513
        $condition = Functions::ifCondition($condition);
2514
        // Loop through arguments
2515
        foreach ($aArgs as $key => $arg) {
2516
            if (!is_numeric($arg)) {
2517
                $arg = \PhpOffice\PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
2518
            }
2519
            $testCondition = '=' . $arg . $condition;
2520
            if (\PhpOffice\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2521
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2522
                    $returnValue = $arg;
2523
                }
2524
            }
2525
        }
2526
2527
        return $returnValue;
2528
    }
2529
2530
    //
2531
    //    Special variant of array_count_values that isn't limited to strings and integers,
2532
    //        but can work with floating point numbers as values
2533
    //
2534 1
    private static function modeCalc($data)
2535
    {
2536 1
        $frequencyArray = [];
2537 1
        foreach ($data as $datum) {
2538 1
            $found = false;
2539 1
            foreach ($frequencyArray as $key => $value) {
2540 1
                if ((string) $value['value'] == (string) $datum) {
2541 1
                    ++$frequencyArray[$key]['frequency'];
2542 1
                    $found = true;
2543 1
                    break;
2544
                }
2545
            }
2546 1
            if (!$found) {
2547 1
                $frequencyArray[] = [
2548 1
                    'value' => $datum,
2549 1
                    'frequency' => 1,
2550
                ];
2551
            }
2552
        }
2553
2554 1
        foreach ($frequencyArray as $key => $value) {
2555 1
            $frequencyList[$key] = $value['frequency'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$frequencyList was never initialized. Although not strictly required by PHP, it is generally a good practice to add $frequencyList = 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...
2556 1
            $valueList[$key] = $value['value'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$valueList was never initialized. Although not strictly required by PHP, it is generally a good practice to add $valueList = 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...
2557
        }
2558 1
        array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
0 ignored issues
show
Bug introduced by
The variable $valueList 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...
2559
2560 1
        if ($frequencyArray[0]['frequency'] == 1) {
2561 1
            return Functions::NA();
2562
        }
2563
2564 1
        return $frequencyArray[0]['value'];
2565
    }
2566
2567
    /**
2568
     * MODE.
2569
     *
2570
     * Returns the most frequently occurring, or repetitive, value in an array or range of data
2571
     *
2572
     * Excel Function:
2573
     *        MODE(value1[,value2[, ...]])
2574
     *
2575
     * @category Statistical Functions
2576
     *
2577
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2578
     *
2579
     * @return    float
2580
     */
2581 1
    public static function MODE()
2582
    {
2583 1
        $returnValue = Functions::NA();
2584
2585
        // Loop through arguments
2586 1
        $aArgs = Functions::flattenArray(func_get_args());
2587
2588 1
        $mArgs = [];
2589 1
        foreach ($aArgs as $arg) {
2590
            // Is it a numeric value?
2591 1
            if ((is_numeric($arg)) && (!is_string($arg))) {
2592 1
                $mArgs[] = $arg;
2593
            }
2594
        }
2595
2596 1
        if (!empty($mArgs)) {
2597 1
            return self::modeCalc($mArgs);
2598
        }
2599
2600
        return $returnValue;
2601
    }
2602
2603
    /**
2604
     * NEGBINOMDIST.
2605
     *
2606
     * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
2607
     *        there will be number_f failures before the number_s-th success, when the constant
2608
     *        probability of a success is probability_s. This function is similar to the binomial
2609
     *        distribution, except that the number of successes is fixed, and the number of trials is
2610
     *        variable. Like the binomial, trials are assumed to be independent.
2611
     *
2612
     * @param    float        $failures        Number of Failures
2613
     * @param    float        $successes        Threshold number of Successes
2614
     * @param    float        $probability    Probability of success on each trial
2615
     *
2616
     * @return    float
2617
     */
2618
    public static function NEGBINOMDIST($failures, $successes, $probability)
2619
    {
2620
        $failures = floor(Functions::flattenSingleValue($failures));
2621
        $successes = floor(Functions::flattenSingleValue($successes));
2622
        $probability = Functions::flattenSingleValue($probability);
2623
2624
        if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) {
2625
            if (($failures < 0) || ($successes < 1)) {
2626
                return Functions::NAN();
2627
            } elseif (($probability < 0) || ($probability > 1)) {
2628
                return Functions::NAN();
2629
            }
2630
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
2631
                if (($failures + $successes - 1) <= 0) {
2632
                    return Functions::NAN();
2633
                }
2634
            }
2635
2636
            return (MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures));
2637
        }
2638
2639
        return Functions::VALUE();
2640
    }
2641
2642
    /**
2643
     * NORMDIST.
2644
     *
2645
     * Returns the normal distribution for the specified mean and standard deviation. This
2646
     * function has a very wide range of applications in statistics, including hypothesis
2647
     * testing.
2648
     *
2649
     * @param    float        $value
2650
     * @param    float        $mean        Mean Value
2651
     * @param    float        $stdDev        Standard Deviation
2652
     * @param    bool        $cumulative
2653
     *
2654
     * @return    float
2655
     */
2656
    public static function NORMDIST($value, $mean, $stdDev, $cumulative)
2657
    {
2658
        $value = Functions::flattenSingleValue($value);
2659
        $mean = Functions::flattenSingleValue($mean);
2660
        $stdDev = Functions::flattenSingleValue($stdDev);
2661
2662
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2663
            if ($stdDev < 0) {
2664
                return Functions::NAN();
2665
            }
2666
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2667
                if ($cumulative) {
2668
                    return 0.5 * (1 + Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2))));
2669
                }
2670
2671
                return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev))));
2672
            }
2673
        }
2674
2675
        return Functions::VALUE();
2676
    }
2677
2678
    /**
2679
     * NORMINV.
2680
     *
2681
     * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
2682
     *
2683
     * @param    float        $probability
2684
     * @param    float        $mean        Mean Value
2685
     * @param    float        $stdDev        Standard Deviation
2686
     *
2687
     * @return    float
2688
     */
2689 View Code Duplication
    public static function NORMINV($probability, $mean, $stdDev)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2690
    {
2691
        $probability = Functions::flattenSingleValue($probability);
2692
        $mean = Functions::flattenSingleValue($mean);
2693
        $stdDev = Functions::flattenSingleValue($stdDev);
2694
2695
        if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2696
            if (($probability < 0) || ($probability > 1)) {
2697
                return Functions::NAN();
2698
            }
2699
            if ($stdDev < 0) {
2700
                return Functions::NAN();
2701
            }
2702
2703
            return (self::inverseNcdf($probability) * $stdDev) + $mean;
2704
        }
2705
2706
        return Functions::VALUE();
2707
    }
2708
2709
    /**
2710
     * NORMSDIST.
2711
     *
2712
     * Returns the standard normal cumulative distribution function. The distribution has
2713
     * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
2714
     * table of standard normal curve areas.
2715
     *
2716
     * @param    float        $value
2717
     *
2718
     * @return    float
2719
     */
2720
    public static function NORMSDIST($value)
2721
    {
2722
        $value = Functions::flattenSingleValue($value);
2723
2724
        return self::NORMDIST($value, 0, 1, true);
2725
    }
2726
2727
    /**
2728
     * NORMSINV.
2729
     *
2730
     * Returns the inverse of the standard normal cumulative distribution
2731
     *
2732
     * @param    float        $value
2733
     *
2734
     * @return    float
2735
     */
2736
    public static function NORMSINV($value)
2737
    {
2738
        return self::NORMINV($value, 0, 1);
2739
    }
2740
2741
    /**
2742
     * PERCENTILE.
2743
     *
2744
     * Returns the nth percentile of values in a range..
2745
     *
2746
     * Excel Function:
2747
     *        PERCENTILE(value1[,value2[, ...]],entry)
2748
     *
2749
     * @category Statistical Functions
2750
     *
2751
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2752
     * @param    float        $entry            Percentile value in the range 0..1, inclusive.
0 ignored issues
show
Bug introduced by
There is no parameter named $entry. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2753
     *
2754
     * @return    float
2755
     */
2756
    public static function PERCENTILE()
2757
    {
2758
        $aArgs = Functions::flattenArray(func_get_args());
2759
2760
        // Calculate
2761
        $entry = array_pop($aArgs);
2762
2763
        if ((is_numeric($entry)) && (!is_string($entry))) {
2764
            if (($entry < 0) || ($entry > 1)) {
2765
                return Functions::NAN();
2766
            }
2767
            $mArgs = [];
2768
            foreach ($aArgs as $arg) {
2769
                // Is it a numeric value?
2770
                if ((is_numeric($arg)) && (!is_string($arg))) {
2771
                    $mArgs[] = $arg;
2772
                }
2773
            }
2774
            $mValueCount = count($mArgs);
2775
            if ($mValueCount > 0) {
2776
                sort($mArgs);
2777
                $count = self::COUNT($mArgs);
2778
                $index = $entry * ($count - 1);
2779
                $iBase = floor($index);
2780
                if ($index == $iBase) {
2781
                    return $mArgs[$index];
2782
                }
2783
                $iNext = $iBase + 1;
2784
                $iProportion = $index - $iBase;
2785
2786
                return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion);
2787
            }
2788
        }
2789
2790
        return Functions::VALUE();
2791
    }
2792
2793
    /**
2794
     * PERCENTRANK.
2795
     *
2796
     * Returns the rank of a value in a data set as a percentage of the data set.
2797
     *
2798
     * @param    array of number        An array of, or a reference to, a list of numbers
2799
     * @param    number                the number whose rank you want to find
2800
     * @param    number                the number of significant digits for the returned percentage value
2801
     * @param mixed $valueSet
2802
     * @param mixed $value
2803
     * @param mixed $significance
2804
     *
2805
     * @return    float
2806
     */
2807
    public static function PERCENTRANK($valueSet, $value, $significance = 3)
2808
    {
2809
        $valueSet = Functions::flattenArray($valueSet);
2810
        $value = Functions::flattenSingleValue($value);
2811
        $significance = (is_null($significance)) ? 3 : (int) Functions::flattenSingleValue($significance);
2812
2813
        foreach ($valueSet as $key => $valueEntry) {
2814
            if (!is_numeric($valueEntry)) {
2815
                unset($valueSet[$key]);
2816
            }
2817
        }
2818
        sort($valueSet, SORT_NUMERIC);
2819
        $valueCount = count($valueSet);
2820
        if ($valueCount == 0) {
2821
            return Functions::NAN();
2822
        }
2823
2824
        $valueAdjustor = $valueCount - 1;
2825
        if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
2826
            return Functions::NA();
2827
        }
2828
2829
        $pos = array_search($value, $valueSet);
2830
        if ($pos === false) {
2831
            $pos = 0;
2832
            $testValue = $valueSet[0];
2833
            while ($testValue < $value) {
2834
                $testValue = $valueSet[++$pos];
2835
            }
2836
            --$pos;
2837
            $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
2838
        }
2839
2840
        return round($pos / $valueAdjustor, $significance);
2841
    }
2842
2843
    /**
2844
     * PERMUT.
2845
     *
2846
     * Returns the number of permutations for a given number of objects that can be
2847
     *        selected from number objects. A permutation is any set or subset of objects or
2848
     *        events where internal order is significant. Permutations are different from
2849
     *        combinations, for which the internal order is not significant. Use this function
2850
     *        for lottery-style probability calculations.
2851
     *
2852
     * @param    int        $numObjs    Number of different objects
2853
     * @param    int        $numInSet    Number of objects in each permutation
2854
     *
2855
     * @return    int        Number of permutations
2856
     */
2857 View Code Duplication
    public static function PERMUT($numObjs, $numInSet)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2858
    {
2859
        $numObjs = Functions::flattenSingleValue($numObjs);
2860
        $numInSet = Functions::flattenSingleValue($numInSet);
2861
2862
        if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
2863
            $numInSet = floor($numInSet);
2864
            if ($numObjs < $numInSet) {
2865
                return Functions::NAN();
2866
            }
2867
2868
            return round(MathTrig::FACT($numObjs) / MathTrig::FACT($numObjs - $numInSet));
2869
        }
2870
2871
        return Functions::VALUE();
2872
    }
2873
2874
    /**
2875
     * POISSON.
2876
     *
2877
     * Returns the Poisson distribution. A common application of the Poisson distribution
2878
     * is predicting the number of events over a specific time, such as the number of
2879
     * cars arriving at a toll plaza in 1 minute.
2880
     *
2881
     * @param    float        $value
2882
     * @param    float        $mean        Mean Value
2883
     * @param    bool        $cumulative
2884
     *
2885
     * @return    float
2886
     */
2887
    public static function POISSON($value, $mean, $cumulative)
2888
    {
2889
        $value = Functions::flattenSingleValue($value);
2890
        $mean = Functions::flattenSingleValue($mean);
2891
2892
        if ((is_numeric($value)) && (is_numeric($mean))) {
2893
            if (($value < 0) || ($mean <= 0)) {
2894
                return Functions::NAN();
2895
            }
2896
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2897
                if ($cumulative) {
2898
                    $summer = 0;
2899
                    for ($i = 0; $i <= floor($value); ++$i) {
2900
                        $summer += pow($mean, $i) / MathTrig::FACT($i);
2901
                    }
2902
2903
                    return exp(0 - $mean) * $summer;
2904
                }
2905
2906
                return (exp(0 - $mean) * pow($mean, $value)) / MathTrig::FACT($value);
2907
            }
2908
        }
2909
2910
        return Functions::VALUE();
2911
    }
2912
2913
    /**
2914
     * QUARTILE.
2915
     *
2916
     * Returns the quartile of a data set.
2917
     *
2918
     * Excel Function:
2919
     *        QUARTILE(value1[,value2[, ...]],entry)
2920
     *
2921
     * @category Statistical Functions
2922
     *
2923
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2924
     * @param    int            $entry            Quartile value in the range 1..3, inclusive.
0 ignored issues
show
Bug introduced by
There is no parameter named $entry. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
2925
     *
2926
     * @return    float
2927
     */
2928
    public static function QUARTILE()
2929
    {
2930
        $aArgs = Functions::flattenArray(func_get_args());
2931
2932
        // Calculate
2933
        $entry = floor(array_pop($aArgs));
2934
2935
        if ((is_numeric($entry)) && (!is_string($entry))) {
2936
            $entry /= 4;
2937
            if (($entry < 0) || ($entry > 1)) {
2938
                return Functions::NAN();
2939
            }
2940
2941
            return self::PERCENTILE($aArgs, $entry);
2942
        }
2943
2944
        return Functions::VALUE();
2945
    }
2946
2947
    /**
2948
     * RANK.
2949
     *
2950
     * Returns the rank of a number in a list of numbers.
2951
     *
2952
     * @param    number                the number whose rank you want to find
2953
     * @param    array of number        An array of, or a reference to, a list of numbers
2954
     * @param    mixed                Order to sort the values in the value set
2955
     * @param mixed $value
2956
     * @param mixed $valueSet
2957
     * @param mixed $order
2958
     *
2959
     * @return    float
2960
     */
2961
    public static function RANK($value, $valueSet, $order = 0)
2962
    {
2963
        $value = Functions::flattenSingleValue($value);
2964
        $valueSet = Functions::flattenArray($valueSet);
2965
        $order = (is_null($order)) ? 0 : (int) Functions::flattenSingleValue($order);
2966
2967
        foreach ($valueSet as $key => $valueEntry) {
2968
            if (!is_numeric($valueEntry)) {
2969
                unset($valueSet[$key]);
2970
            }
2971
        }
2972
2973
        if ($order == 0) {
2974
            rsort($valueSet, SORT_NUMERIC);
2975
        } else {
2976
            sort($valueSet, SORT_NUMERIC);
2977
        }
2978
        $pos = array_search($value, $valueSet);
2979
        if ($pos === false) {
2980
            return Functions::NA();
2981
        }
2982
2983
        return ++$pos;
2984
    }
2985
2986
    /**
2987
     * RSQ.
2988
     *
2989
     * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
2990
     *
2991
     * @param    array of mixed        Data Series Y
2992
     * @param    array of mixed        Data Series X
2993
     * @param mixed $yValues
2994
     * @param mixed $xValues
2995
     *
2996
     * @return    float
2997
     */
2998 View Code Duplication
    public static function RSQ($yValues, $xValues)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2999
    {
3000
        if (!self::checkTrendArrays($yValues, $xValues)) {
3001
            return Functions::VALUE();
3002
        }
3003
        $yValueCount = count($yValues);
3004
        $xValueCount = count($xValues);
3005
3006
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
3007
            return Functions::NA();
3008
        } elseif ($yValueCount == 1) {
3009
            return Functions::DIV0();
3010
        }
3011
3012
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
3013
3014
        return $bestFitLinear->getGoodnessOfFit();
3015
    }
3016
3017
    /**
3018
     * SKEW.
3019
     *
3020
     * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
3021
     * of a distribution around its mean. Positive skewness indicates a distribution with an
3022
     * asymmetric tail extending toward more positive values. Negative skewness indicates a
3023
     * distribution with an asymmetric tail extending toward more negative values.
3024
     *
3025
     * @param    array    Data Series
3026
     *
3027
     * @return    float
3028
     */
3029
    public static function SKEW()
3030
    {
3031
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3032
        $mean = self::AVERAGE($aArgs);
3033
        $stdDev = self::STDEV($aArgs);
3034
3035
        $count = $summer = 0;
3036
        // Loop through arguments
3037 View Code Duplication
        foreach ($aArgs as $k => $arg) {
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...
3038
            if ((is_bool($arg)) &&
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
3039
                (!Functions::isMatrixValue($k))) {
3040
            } else {
3041
                // Is it a numeric value?
3042
                if ((is_numeric($arg)) && (!is_string($arg))) {
3043
                    $summer += pow((($arg - $mean) / $stdDev), 3);
3044
                    ++$count;
3045
                }
3046
            }
3047
        }
3048
3049
        if ($count > 2) {
3050
            return $summer * ($count / (($count - 1) * ($count - 2)));
3051
        }
3052
3053
        return Functions::DIV0();
3054
    }
3055
3056
    /**
3057
     * SLOPE.
3058
     *
3059
     * Returns the slope of the linear regression line through data points in known_y's and known_x's.
3060
     *
3061
     * @param    array of mixed        Data Series Y
3062
     * @param    array of mixed        Data Series X
3063
     * @param mixed $yValues
3064
     * @param mixed $xValues
3065
     *
3066
     * @return    float
3067
     */
3068 View Code Duplication
    public static function SLOPE($yValues, $xValues)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3069
    {
3070
        if (!self::checkTrendArrays($yValues, $xValues)) {
3071
            return Functions::VALUE();
3072
        }
3073
        $yValueCount = count($yValues);
3074
        $xValueCount = count($xValues);
3075
3076
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
3077
            return Functions::NA();
3078
        } elseif ($yValueCount == 1) {
3079
            return Functions::DIV0();
3080
        }
3081
3082
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
3083
3084
        return $bestFitLinear->getSlope();
3085
    }
3086
3087
    /**
3088
     * SMALL.
3089
     *
3090
     * Returns the nth smallest value in a data set. You can use this function to
3091
     *        select a value based on its relative standing.
3092
     *
3093
     * Excel Function:
3094
     *        SMALL(value1[,value2[, ...]],entry)
3095
     *
3096
     * @category Statistical Functions
3097
     *
3098
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3099
     * @param    int            $entry            Position (ordered from the smallest) in the array or range of data to return
0 ignored issues
show
Bug introduced by
There is no parameter named $entry. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3100
     *
3101
     * @return    float
3102
     */
3103 View Code Duplication
    public static function SMALL()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3104
    {
3105
        $aArgs = Functions::flattenArray(func_get_args());
3106
3107
        // Calculate
3108
        $entry = array_pop($aArgs);
3109
3110
        if ((is_numeric($entry)) && (!is_string($entry))) {
3111
            $mArgs = [];
3112
            foreach ($aArgs as $arg) {
3113
                // Is it a numeric value?
3114
                if ((is_numeric($arg)) && (!is_string($arg))) {
3115
                    $mArgs[] = $arg;
3116
                }
3117
            }
3118
            $count = self::COUNT($mArgs);
3119
            $entry = floor(--$entry);
3120
            if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
3121
                return Functions::NAN();
3122
            }
3123
            sort($mArgs);
3124
3125
            return $mArgs[$entry];
3126
        }
3127
3128
        return Functions::VALUE();
3129
    }
3130
3131
    /**
3132
     * STANDARDIZE.
3133
     *
3134
     * Returns a normalized value from a distribution characterized by mean and standard_dev.
3135
     *
3136
     * @param    float    $value        Value to normalize
3137
     * @param    float    $mean        Mean Value
3138
     * @param    float    $stdDev        Standard Deviation
3139
     *
3140
     * @return    float    Standardized value
3141
     */
3142 View Code Duplication
    public static function STANDARDIZE($value, $mean, $stdDev)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3143
    {
3144
        $value = Functions::flattenSingleValue($value);
3145
        $mean = Functions::flattenSingleValue($mean);
3146
        $stdDev = Functions::flattenSingleValue($stdDev);
3147
3148
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
3149
            if ($stdDev <= 0) {
3150
                return Functions::NAN();
3151
            }
3152
3153
            return ($value - $mean) / $stdDev;
3154
        }
3155
3156
        return Functions::VALUE();
3157
    }
3158
3159
    /**
3160
     * STDEV.
3161
     *
3162
     * Estimates standard deviation based on a sample. The standard deviation is a measure of how
3163
     *        widely values are dispersed from the average value (the mean).
3164
     *
3165
     * Excel Function:
3166
     *        STDEV(value1[,value2[, ...]])
3167
     *
3168
     * @category Statistical Functions
3169
     *
3170
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3171
     *
3172
     * @return    float
3173
     */
3174 1 View Code Duplication
    public static function STDEV()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3175
    {
3176 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3177
3178
        // Return value
3179 1
        $returnValue = null;
3180
3181 1
        $aMean = self::AVERAGE($aArgs);
3182 1
        if (!is_null($aMean)) {
3183 1
            $aCount = -1;
3184 1
            foreach ($aArgs as $k => $arg) {
3185 1
                if ((is_bool($arg)) &&
3186 1
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
3187
                    $arg = (int) $arg;
3188
                }
3189
                // Is it a numeric value?
3190 1
                if ((is_numeric($arg)) && (!is_string($arg))) {
3191 1
                    if (is_null($returnValue)) {
3192 1
                        $returnValue = pow(($arg - $aMean), 2);
3193
                    } else {
3194 1
                        $returnValue += pow(($arg - $aMean), 2);
3195
                    }
3196 1
                    ++$aCount;
3197
                }
3198
            }
3199
3200
            // Return
3201 1
            if (($aCount > 0) && ($returnValue >= 0)) {
3202 1
                return sqrt($returnValue / $aCount);
3203
            }
3204
        }
3205
3206
        return Functions::DIV0();
3207
    }
3208
3209
    /**
3210
     * STDEVA.
3211
     *
3212
     * Estimates standard deviation based on a sample, including numbers, text, and logical values
3213
     *
3214
     * Excel Function:
3215
     *        STDEVA(value1[,value2[, ...]])
3216
     *
3217
     * @category Statistical Functions
3218
     *
3219
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3220
     *
3221
     * @return    float
3222
     */
3223 1 View Code Duplication
    public static function STDEVA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3224
    {
3225 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3226
3227 1
        $returnValue = null;
3228
3229 1
        $aMean = self::AVERAGEA($aArgs);
3230 1
        if (!is_null($aMean)) {
3231 1
            $aCount = -1;
3232 1
            foreach ($aArgs as $k => $arg) {
3233 1
                if ((is_bool($arg)) &&
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
3234 1
                    (!Functions::isMatrixValue($k))) {
3235
                } else {
3236
                    // Is it a numeric value?
3237 1
                    if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3238 1
                        if (is_bool($arg)) {
3239 1
                            $arg = (int) $arg;
3240 1
                        } elseif (is_string($arg)) {
3241 1
                            $arg = 0;
3242
                        }
3243 1
                        if (is_null($returnValue)) {
3244 1
                            $returnValue = pow(($arg - $aMean), 2);
3245
                        } else {
3246 1
                            $returnValue += pow(($arg - $aMean), 2);
3247
                        }
3248 1
                        ++$aCount;
3249
                    }
3250
                }
3251
            }
3252
3253 1
            if (($aCount > 0) && ($returnValue >= 0)) {
3254 1
                return sqrt($returnValue / $aCount);
3255
            }
3256
        }
3257
3258
        return Functions::DIV0();
3259
    }
3260
3261
    /**
3262
     * STDEVP.
3263
     *
3264
     * Calculates standard deviation based on the entire population
3265
     *
3266
     * Excel Function:
3267
     *        STDEVP(value1[,value2[, ...]])
3268
     *
3269
     * @category Statistical Functions
3270
     *
3271
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3272
     *
3273
     * @return    float
3274
     */
3275 1 View Code Duplication
    public static function STDEVP()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3276
    {
3277 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3278
3279 1
        $returnValue = null;
3280
3281 1
        $aMean = self::AVERAGE($aArgs);
3282 1
        if (!is_null($aMean)) {
3283 1
            $aCount = 0;
3284 1
            foreach ($aArgs as $k => $arg) {
3285 1
                if ((is_bool($arg)) &&
3286 1
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
3287
                    $arg = (int) $arg;
3288
                }
3289
                // Is it a numeric value?
3290 1
                if ((is_numeric($arg)) && (!is_string($arg))) {
3291 1
                    if (is_null($returnValue)) {
3292 1
                        $returnValue = pow(($arg - $aMean), 2);
3293
                    } else {
3294 1
                        $returnValue += pow(($arg - $aMean), 2);
3295
                    }
3296 1
                    ++$aCount;
3297
                }
3298
            }
3299
3300 1
            if (($aCount > 0) && ($returnValue >= 0)) {
3301 1
                return sqrt($returnValue / $aCount);
3302
            }
3303
        }
3304
3305
        return Functions::DIV0();
3306
    }
3307
3308
    /**
3309
     * STDEVPA.
3310
     *
3311
     * Calculates standard deviation based on the entire population, including numbers, text, and logical values
3312
     *
3313
     * Excel Function:
3314
     *        STDEVPA(value1[,value2[, ...]])
3315
     *
3316
     * @category Statistical Functions
3317
     *
3318
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3319
     *
3320
     * @return    float
3321
     */
3322 1 View Code Duplication
    public static function STDEVPA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3323
    {
3324 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3325
3326 1
        $returnValue = null;
3327
3328 1
        $aMean = self::AVERAGEA($aArgs);
3329 1
        if (!is_null($aMean)) {
3330 1
            $aCount = 0;
3331 1
            foreach ($aArgs as $k => $arg) {
3332 1
                if ((is_bool($arg)) &&
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
3333 1
                    (!Functions::isMatrixValue($k))) {
3334
                } else {
3335
                    // Is it a numeric value?
3336 1
                    if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3337 1
                        if (is_bool($arg)) {
3338 1
                            $arg = (int) $arg;
3339 1
                        } elseif (is_string($arg)) {
3340 1
                            $arg = 0;
3341
                        }
3342 1
                        if (is_null($returnValue)) {
3343 1
                            $returnValue = pow(($arg - $aMean), 2);
3344
                        } else {
3345 1
                            $returnValue += pow(($arg - $aMean), 2);
3346
                        }
3347 1
                        ++$aCount;
3348
                    }
3349
                }
3350
            }
3351
3352 1
            if (($aCount > 0) && ($returnValue >= 0)) {
3353 1
                return sqrt($returnValue / $aCount);
3354
            }
3355
        }
3356
3357
        return Functions::DIV0();
3358
    }
3359
3360
    /**
3361
     * STEYX.
3362
     *
3363
     * Returns the standard error of the predicted y-value for each x in the regression.
3364
     *
3365
     * @param    array of mixed        Data Series Y
3366
     * @param    array of mixed        Data Series X
3367
     * @param mixed $yValues
3368
     * @param mixed $xValues
3369
     *
3370
     * @return    float
3371
     */
3372 View Code Duplication
    public static function STEYX($yValues, $xValues)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3373
    {
3374
        if (!self::checkTrendArrays($yValues, $xValues)) {
3375
            return Functions::VALUE();
3376
        }
3377
        $yValueCount = count($yValues);
3378
        $xValueCount = count($xValues);
3379
3380
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
3381
            return Functions::NA();
3382
        } elseif ($yValueCount == 1) {
3383
            return Functions::DIV0();
3384
        }
3385
3386
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
3387
3388
        return $bestFitLinear->getStdevOfResiduals();
3389
    }
3390
3391
    /**
3392
     * TDIST.
3393
     *
3394
     * Returns the probability of Student's T distribution.
3395
     *
3396
     * @param    float        $value            Value for the function
3397
     * @param    float        $degrees        degrees of freedom
3398
     * @param    float        $tails            number of tails (1 or 2)
3399
     *
3400
     * @return    float
3401
     */
3402
    public static function TDIST($value, $degrees, $tails)
3403
    {
3404
        $value = Functions::flattenSingleValue($value);
3405
        $degrees = floor(Functions::flattenSingleValue($degrees));
3406
        $tails = floor(Functions::flattenSingleValue($tails));
3407
3408
        if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) {
3409
            if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
3410
                return Functions::NAN();
3411
            }
3412
            //    tdist, which finds the probability that corresponds to a given value
3413
            //    of t with k degrees of freedom. This algorithm is translated from a
3414
            //    pascal function on p81 of "Statistical Computing in Pascal" by D
3415
            //    Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
3416
            //    London). The above Pascal algorithm is itself a translation of the
3417
            //    fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
3418
            //    Laboratory as reported in (among other places) "Applied Statistics
3419
            //    Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
3420
            //    Horwood Ltd.; W. Sussex, England).
3421
            $tterm = $degrees;
3422
            $ttheta = atan2($value, sqrt($tterm));
3423
            $tc = cos($ttheta);
3424
            $ts = sin($ttheta);
3425
            $tsum = 0;
0 ignored issues
show
Unused Code introduced by
$tsum is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
3426
3427
            if (($degrees % 2) == 1) {
3428
                $ti = 3;
3429
                $tterm = $tc;
3430
            } else {
3431
                $ti = 2;
3432
                $tterm = 1;
3433
            }
3434
3435
            $tsum = $tterm;
3436
            while ($ti < $degrees) {
3437
                $tterm *= $tc * $tc * ($ti - 1) / $ti;
3438
                $tsum += $tterm;
3439
                $ti += 2;
3440
            }
3441
            $tsum *= $ts;
3442
            if (($degrees % 2) == 1) {
3443
                $tsum = M_2DIVPI * ($tsum + $ttheta);
3444
            }
3445
            $tValue = 0.5 * (1 + $tsum);
3446
            if ($tails == 1) {
3447
                return 1 - abs($tValue);
3448
            }
3449
3450
            return 1 - abs((1 - $tValue) - $tValue);
3451
        }
3452
3453
        return Functions::VALUE();
3454
    }
3455
3456
    /**
3457
     * TINV.
3458
     *
3459
     * Returns the one-tailed probability of the chi-squared distribution.
3460
     *
3461
     * @param    float        $probability    Probability for the function
3462
     * @param    float        $degrees        degrees of freedom
3463
     *
3464
     * @return    float
3465
     */
3466 View Code Duplication
    public static function TINV($probability, $degrees)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3467
    {
3468
        $probability = Functions::flattenSingleValue($probability);
3469
        $degrees = floor(Functions::flattenSingleValue($degrees));
3470
3471
        if ((is_numeric($probability)) && (is_numeric($degrees))) {
3472
            $xLo = 100;
3473
            $xHi = 0;
3474
3475
            $x = $xNew = 1;
3476
            $dx = 1;
3477
            $i = 0;
3478
3479
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
3480
                // Apply Newton-Raphson step
3481
                $result = self::TDIST($x, $degrees, 2);
3482
                $error = $result - $probability;
3483
                if ($error == 0.0) {
3484
                    $dx = 0;
3485
                } elseif ($error < 0.0) {
3486
                    $xLo = $x;
3487
                } else {
3488
                    $xHi = $x;
3489
                }
3490
                // Avoid division by zero
3491
                if ($result != 0.0) {
3492
                    $dx = $error / $result;
3493
                    $xNew = $x - $dx;
3494
                }
3495
                // If the NR fails to converge (which for example may be the
3496
                // case if the initial guess is too rough) we apply a bisection
3497
                // step to determine a more narrow interval around the root.
3498
                if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
3499
                    $xNew = ($xLo + $xHi) / 2;
3500
                    $dx = $xNew - $x;
3501
                }
3502
                $x = $xNew;
3503
            }
3504
            if ($i == MAX_ITERATIONS) {
3505
                return Functions::NA();
3506
            }
3507
3508
            return round($x, 12);
3509
        }
3510
3511
        return Functions::VALUE();
3512
    }
3513
3514
    /**
3515
     * TREND.
3516
     *
3517
     * Returns values along a linear Trend
3518
     *
3519
     * @param    array of mixed        Data Series Y
3520
     * @param    array of mixed        Data Series X
3521
     * @param    array of mixed        Values of X for which we want to find Y
3522
     * @param    bool                a logical value specifying whether to force the intersect to equal 0
3523
     * @param mixed $yValues
3524
     * @param mixed $xValues
3525
     * @param mixed $newValues
3526
     * @param mixed $const
3527
     *
3528
     * @return    array of float
3529
     */
3530 View Code Duplication
    public static function TREND($yValues, $xValues = [], $newValues = [], $const = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3531
    {
3532
        $yValues = Functions::flattenArray($yValues);
3533
        $xValues = Functions::flattenArray($xValues);
3534
        $newValues = Functions::flattenArray($newValues);
3535
        $const = (is_null($const)) ? true : (bool) Functions::flattenSingleValue($const);
3536
3537
        $bestFitLinear = \PhpOffice\PhpSpreadsheet\Shared\trend\trend::calculate(\PhpOffice\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues, $const);
3538
        if (empty($newValues)) {
3539
            $newValues = $bestFitLinear->getXValues();
3540
        }
3541
3542
        $returnArray = [];
3543
        foreach ($newValues as $xValue) {
3544
            $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
3545
        }
3546
3547
        return $returnArray;
3548
    }
3549
3550
    /**
3551
     * TRIMMEAN.
3552
     *
3553
     * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
3554
     *        taken by excluding a percentage of data points from the top and bottom tails
3555
     *        of a data set.
3556
     *
3557
     * Excel Function:
3558
     *        TRIMEAN(value1[,value2[, ...]], $discard)
3559
     *
3560
     * @category Statistical Functions
3561
     *
3562
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3563
     * @param    float        $discard        Percentage to discard
0 ignored issues
show
Bug introduced by
There is no parameter named $discard. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3564
     *
3565
     * @return    float
3566
     */
3567
    public static function TRIMMEAN()
3568
    {
3569
        $aArgs = Functions::flattenArray(func_get_args());
3570
3571
        // Calculate
3572
        $percent = array_pop($aArgs);
3573
3574
        if ((is_numeric($percent)) && (!is_string($percent))) {
3575
            if (($percent < 0) || ($percent > 1)) {
3576
                return Functions::NAN();
3577
            }
3578
            $mArgs = [];
3579
            foreach ($aArgs as $arg) {
3580
                // Is it a numeric value?
3581
                if ((is_numeric($arg)) && (!is_string($arg))) {
3582
                    $mArgs[] = $arg;
3583
                }
3584
            }
3585
            $discard = floor(self::COUNT($mArgs) * $percent / 2);
3586
            sort($mArgs);
3587
            for ($i = 0; $i < $discard; ++$i) {
3588
                array_pop($mArgs);
3589
                array_shift($mArgs);
3590
            }
3591
3592
            return self::AVERAGE($mArgs);
3593
        }
3594
3595
        return Functions::VALUE();
3596
    }
3597
3598
    /**
3599
     * VARFunc.
3600
     *
3601
     * Estimates variance based on a sample.
3602
     *
3603
     * Excel Function:
3604
     *        VAR(value1[,value2[, ...]])
3605
     *
3606
     * @category Statistical Functions
3607
     *
3608
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3609
     *
3610
     * @return    float
3611
     */
3612 1 View Code Duplication
    public static function VARFunc()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3613
    {
3614 1
        $returnValue = Functions::DIV0();
3615
3616 1
        $summerA = $summerB = 0;
3617
3618
        // Loop through arguments
3619 1
        $aArgs = Functions::flattenArray(func_get_args());
3620 1
        $aCount = 0;
3621 1
        foreach ($aArgs as $arg) {
3622 1
            if (is_bool($arg)) {
3623 1
                $arg = (int) $arg;
3624
            }
3625
            // Is it a numeric value?
3626 1
            if ((is_numeric($arg)) && (!is_string($arg))) {
3627 1
                $summerA += ($arg * $arg);
3628 1
                $summerB += $arg;
3629 1
                ++$aCount;
3630
            }
3631
        }
3632
3633 1
        if ($aCount > 1) {
3634 1
            $summerA *= $aCount;
3635 1
            $summerB *= $summerB;
3636 1
            $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3637
        }
3638
3639 1
        return $returnValue;
3640
    }
3641
3642
    /**
3643
     * VARA.
3644
     *
3645
     * Estimates variance based on a sample, including numbers, text, and logical values
3646
     *
3647
     * Excel Function:
3648
     *        VARA(value1[,value2[, ...]])
3649
     *
3650
     * @category Statistical Functions
3651
     *
3652
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3653
     *
3654
     * @return    float
3655
     */
3656 1 View Code Duplication
    public static function VARA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3657
    {
3658 1
        $returnValue = Functions::DIV0();
3659
3660 1
        $summerA = $summerB = 0;
3661
3662
        // Loop through arguments
3663 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3664 1
        $aCount = 0;
3665 1
        foreach ($aArgs as $k => $arg) {
3666 1
            if ((is_string($arg)) &&
3667 1
                (Functions::isValue($k))) {
3668
                return Functions::VALUE();
3669 1
            } elseif ((is_string($arg)) &&
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
3670 1
                (!Functions::isMatrixValue($k))) {
3671
            } else {
3672
                // Is it a numeric value?
3673 1
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3674 1
                    if (is_bool($arg)) {
3675 1
                        $arg = (int) $arg;
3676 1
                    } elseif (is_string($arg)) {
3677 1
                        $arg = 0;
3678
                    }
3679 1
                    $summerA += ($arg * $arg);
3680 1
                    $summerB += $arg;
3681 1
                    ++$aCount;
3682
                }
3683
            }
3684
        }
3685
3686 1
        if ($aCount > 1) {
3687 1
            $summerA *= $aCount;
3688 1
            $summerB *= $summerB;
3689 1
            $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3690
        }
3691
3692 1
        return $returnValue;
3693
    }
3694
3695
    /**
3696
     * VARP.
3697
     *
3698
     * Calculates variance based on the entire population
3699
     *
3700
     * Excel Function:
3701
     *        VARP(value1[,value2[, ...]])
3702
     *
3703
     * @category Statistical Functions
3704
     *
3705
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3706
     *
3707
     * @return    float
3708
     */
3709 1 View Code Duplication
    public static function VARP()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3710
    {
3711
        // Return value
3712 1
        $returnValue = Functions::DIV0();
3713
3714 1
        $summerA = $summerB = 0;
3715
3716
        // Loop through arguments
3717 1
        $aArgs = Functions::flattenArray(func_get_args());
3718 1
        $aCount = 0;
3719 1
        foreach ($aArgs as $arg) {
3720 1
            if (is_bool($arg)) {
3721 1
                $arg = (int) $arg;
3722
            }
3723
            // Is it a numeric value?
3724 1
            if ((is_numeric($arg)) && (!is_string($arg))) {
3725 1
                $summerA += ($arg * $arg);
3726 1
                $summerB += $arg;
3727 1
                ++$aCount;
3728
            }
3729
        }
3730
3731 1
        if ($aCount > 0) {
3732 1
            $summerA *= $aCount;
3733 1
            $summerB *= $summerB;
3734 1
            $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3735
        }
3736
3737 1
        return $returnValue;
3738
    }
3739
3740
    /**
3741
     * VARPA.
3742
     *
3743
     * Calculates variance based on the entire population, including numbers, text, and logical values
3744
     *
3745
     * Excel Function:
3746
     *        VARPA(value1[,value2[, ...]])
3747
     *
3748
     * @category Statistical Functions
3749
     *
3750
     * @param    mixed        $arg,...        Data values
0 ignored issues
show
Bug introduced by
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
3751
     *
3752
     * @return    float
3753
     */
3754 1 View Code Duplication
    public static function VARPA()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
3755
    {
3756 1
        $returnValue = Functions::DIV0();
3757
3758 1
        $summerA = $summerB = 0;
3759
3760
        // Loop through arguments
3761 1
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3762 1
        $aCount = 0;
3763 1
        foreach ($aArgs as $k => $arg) {
3764 1
            if ((is_string($arg)) &&
3765 1
                (Functions::isValue($k))) {
3766
                return Functions::VALUE();
3767 1
            } elseif ((is_string($arg)) &&
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
3768 1
                (!Functions::isMatrixValue($k))) {
3769
            } else {
3770
                // Is it a numeric value?
3771 1
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3772 1
                    if (is_bool($arg)) {
3773 1
                        $arg = (int) $arg;
3774 1
                    } elseif (is_string($arg)) {
3775 1
                        $arg = 0;
3776
                    }
3777 1
                    $summerA += ($arg * $arg);
3778 1
                    $summerB += $arg;
3779 1
                    ++$aCount;
3780
                }
3781
            }
3782
        }
3783
3784 1
        if ($aCount > 0) {
3785 1
            $summerA *= $aCount;
3786 1
            $summerB *= $summerB;
3787 1
            $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3788
        }
3789
3790 1
        return $returnValue;
3791
    }
3792
3793
    /**
3794
     * WEIBULL.
3795
     *
3796
     * Returns the Weibull distribution. Use this distribution in reliability
3797
     * analysis, such as calculating a device's mean time to failure.
3798
     *
3799
     * @param    float        $value
3800
     * @param    float        $alpha        Alpha Parameter
3801
     * @param    float        $beta        Beta Parameter
3802
     * @param    bool        $cumulative
3803
     *
3804
     * @return    float
3805
     */
3806
    public static function WEIBULL($value, $alpha, $beta, $cumulative)
3807
    {
3808
        $value = Functions::flattenSingleValue($value);
3809
        $alpha = Functions::flattenSingleValue($alpha);
3810
        $beta = Functions::flattenSingleValue($beta);
3811
3812
        if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) {
3813
            if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) {
3814
                return Functions::NAN();
3815
            }
3816
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
3817
                if ($cumulative) {
3818
                    return 1 - exp(0 - pow($value / $beta, $alpha));
3819
                }
3820
3821
                return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha));
3822
            }
3823
        }
3824
3825
        return Functions::VALUE();
3826
    }
3827
3828
    /**
3829
     * ZTEST.
3830
     *
3831
     * Returns the Weibull distribution. Use this distribution in reliability
3832
     * analysis, such as calculating a device's mean time to failure.
3833
     *
3834
     * @param    float        $dataSet
3835
     * @param    float        $m0        Alpha Parameter
3836
     * @param    float        $sigma    Beta Parameter
3837
     *
3838
     * @return    float
3839
     */
3840
    public static function ZTEST($dataSet, $m0, $sigma = null)
3841
    {
3842
        $dataSet = Functions::flattenArrayIndexed($dataSet);
0 ignored issues
show
Documentation introduced by
$dataSet is of type double, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
3843
        $m0 = Functions::flattenSingleValue($m0);
3844
        $sigma = Functions::flattenSingleValue($sigma);
3845
3846
        if (is_null($sigma)) {
3847
            $sigma = self::STDEV($dataSet);
3848
        }
3849
        $n = count($dataSet);
3850
3851
        return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / sqrt($n)));
3852
    }
3853
}
3854