Completed
Push — develop ( e1f81f...539a89 )
by Adrien
16:11
created

Statistical::PERCENTILE()   D

Complexity

Conditions 10
Paths 5

Size

Total Lines 35
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 23
nc 5
nop 0
dl 0
loc 35
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpSpreadsheet\Calculation;
4
5
/** LOG_GAMMA_X_MAX_VALUE */
6
define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
7
8
/** XMININ */
9
define('XMININ', 2.23e-308);
10
11
/** EPS */
12
define('EPS', 2.22e-16);
13
14
/** SQRT2PI */
15
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
 * @copyright   Copyright (c) 2006 - 2016 PhpSpreadsheet (https://github.com/PHPOffice/PhpSpreadsheet)
36
 * @license     http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
37
 * @version     ##VERSION##, ##DATE##
38
 */
39
class Statistical
40
{
41
    private static function checkTrendArrays(&$array1, &$array2)
42
    {
43
        if (!is_array($array1)) {
44
            $array1 = array($array1);
45
        }
46
        if (!is_array($array2)) {
47
            $array2 = array($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]);
55
                unset($array2[$key]);
56
            }
57
        }
58 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...
59
            if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
60
                unset($array1[$key]);
61
                unset($array2[$key]);
62
            }
63
        }
64
        $array1 = array_merge($array1);
65
        $array2 = array_merge($array2);
66
67
        return true;
68
    }
69
70
71
    /**
72
     * Beta function.
73
     *
74
     * @author Jaco van Kooten
75
     *
76
     * @param p require p>0
77
     * @param q require q>0
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
        if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) {
83
            return 0.0;
84
        } else {
85
            return exp(self::logBeta($p, $q));
86
        }
87
    }
88
89
90
    /**
91
     * Incomplete beta function
92
     *
93
     * @author Jaco van Kooten
94
     * @author Paul Meagher
95
     *
96
     * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
97
     * @param x require 0<=x<=1
98
     * @param p require p>0
99
     * @param q require q>0
100
     * @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...
101
     */
102
    private static function incompleteBeta($x, $p, $q)
103
    {
104
        if ($x <= 0.0) {
105
            return 0.0;
106
        } elseif ($x >= 1.0) {
107
            return 1.0;
108
        } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
109
            return 0.0;
110
        }
111
        $beta_gam = exp((0 - self::logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x));
112
        if ($x < ($p + 1.0) / ($p + $q + 2.0)) {
113
            return $beta_gam * self::betaFraction($x, $p, $q) / $p;
114
        } else {
115
            return 1.0 - ($beta_gam * self::betaFraction(1 - $x, $q, $p) / $q);
116
        }
117
    }
118
119
120
    // Function cache for logBeta function
121
    private static $logBetaCacheP      = 0.0;
122
    private static $logBetaCacheQ      = 0.0;
123
    private static $logBetaCacheResult = 0.0;
124
125
    /**
126
     * The natural logarithm of the beta function.
127
     *
128
     * @param p require p>0
129
     * @param q require q>0
130
     * @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...
131
     * @author Jaco van Kooten
132
     */
133
    private static function logBeta($p, $q)
134
    {
135
        if ($p != self::$logBetaCacheP || $q != self::$logBetaCacheQ) {
136
            self::$logBetaCacheP = $p;
137
            self::$logBetaCacheQ = $q;
138
            if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
139
                self::$logBetaCacheResult = 0.0;
140
            } else {
141
                self::$logBetaCacheResult = self::logGamma($p) + self::logGamma($q) - self::logGamma($p + $q);
142
            }
143
        }
144
        return self::$logBetaCacheResult;
145
    }
146
147
148
    /**
149
     * Evaluates of continued fraction part of incomplete beta function.
150
     * Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
151
     * @author Jaco van Kooten
152
     */
153
    private static function betaFraction($x, $p, $q)
154
    {
155
        $c = 1.0;
156
        $sum_pq = $p + $q;
157
        $p_plus = $p + 1.0;
158
        $p_minus = $p - 1.0;
159
        $h = 1.0 - $sum_pq * $x / $p_plus;
160
        if (abs($h) < XMININ) {
161
            $h = XMININ;
162
        }
163
        $h = 1.0 / $h;
164
        $frac = $h;
165
        $m     = 1;
166
        $delta = 0.0;
167
        while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION) {
168
            $m2 = 2 * $m;
169
            // even index for d
170
            $d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2));
171
            $h = 1.0 + $d * $h;
172
            if (abs($h) < XMININ) {
173
                $h = XMININ;
174
            }
175
            $h = 1.0 / $h;
176
            $c = 1.0 + $d / $c;
177
            if (abs($c) < XMININ) {
178
                $c = XMININ;
179
            }
180
            $frac *= $h * $c;
181
            // odd index for d
182
            $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $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
            $delta = $h * $c;
193
            $frac *= $delta;
194
            ++$m;
195
        }
196
        return $frac;
197
    }
198
199
200
    /**
201
     * logGamma function
202
     *
203
     * @version 1.1
204
     * @author Jaco van Kooten
205
     *
206
     * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher.
207
     *
208
     * The natural logarithm of the gamma function. <br />
209
     * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz <br />
210
     * Applied Mathematics Division <br />
211
     * Argonne National Laboratory <br />
212
     * Argonne, IL 60439 <br />
213
     * <p>
214
     * References:
215
     * <ol>
216
     * <li>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural
217
     *     Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.</li>
218
     * <li>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.</li>
219
     * <li>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.</li>
220
     * </ol>
221
     * </p>
222
     * <p>
223
     * From the original documentation:
224
     * </p>
225
     * <p>
226
     * This routine calculates the LOG(GAMMA) function for a positive real argument X.
227
     * Computation is based on an algorithm outlined in references 1 and 2.
228
     * The program uses rational functions that theoretically approximate LOG(GAMMA)
229
     * to at least 18 significant decimal digits. The approximation for X > 12 is from
230
     * reference 3, while approximations for X < 12.0 are similar to those in reference
231
     * 1, but are unpublished. The accuracy achieved depends on the arithmetic system,
232
     * the compiler, the intrinsic functions, and proper selection of the
233
     * machine-dependent constants.
234
     * </p>
235
     * <p>
236
     * Error returns: <br />
237
     * The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
238
     * The computation is believed to be free of underflow and overflow.
239
     * </p>
240
     * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
241
     */
242
243
    // Function cache for logGamma
244
    private static $logGammaCacheResult = 0.0;
245
    private static $logGammaCacheX      = 0.0;
246
247
    private static function logGamma($x)
248
    {
249
        // Log Gamma related constants
250
        static $lg_d1 = -0.5772156649015328605195174;
251
        static $lg_d2 = 0.4227843350984671393993777;
252
        static $lg_d4 = 1.791759469228055000094023;
253
254
        static $lg_p1 = array(
255
            4.945235359296727046734888,
256
            201.8112620856775083915565,
257
            2290.838373831346393026739,
258
            11319.67205903380828685045,
259
            28557.24635671635335736389,
260
            38484.96228443793359990269,
261
            26377.48787624195437963534,
262
            7225.813979700288197698961
263
        );
264
        static $lg_p2 = array(
265
            4.974607845568932035012064,
266
            542.4138599891070494101986,
267
            15506.93864978364947665077,
268
            184793.2904445632425417223,
269
            1088204.76946882876749847,
270
            3338152.967987029735917223,
271
            5106661.678927352456275255,
272
            3074109.054850539556250927
273
        );
274
        static $lg_p4 = array(
275
            14745.02166059939948905062,
276
            2426813.369486704502836312,
277
            121475557.4045093227939592,
278
            2663432449.630976949898078,
279
            29403789566.34553899906876,
280
            170266573776.5398868392998,
281
            492612579337.743088758812,
282
            560625185622.3951465078242
283
        );
284
        static $lg_q1 = array(
285
            67.48212550303777196073036,
286
            1113.332393857199323513008,
287
            7738.757056935398733233834,
288
            27639.87074403340708898585,
289
            54993.10206226157329794414,
290
            61611.22180066002127833352,
291
            36351.27591501940507276287,
292
            8785.536302431013170870835
293
        );
294
        static $lg_q2 = array(
295
            183.0328399370592604055942,
296
            7765.049321445005871323047,
297
            133190.3827966074194402448,
298
            1136705.821321969608938755,
299
            5267964.117437946917577538,
300
            13467014.54311101692290052,
301
            17827365.30353274213975932,
302
            9533095.591844353613395747
303
        );
304
        static $lg_q4 = array(
305
            2690.530175870899333379843,
306
            639388.5654300092398984238,
307
            41355999.30241388052042842,
308
            1120872109.61614794137657,
309
            14886137286.78813811542398,
310
            101680358627.2438228077304,
311
            341747634550.7377132798597,
312
            446315818741.9713286462081
313
        );
314
        static $lg_c  = array(
315
            -0.001910444077728,
316
            8.4171387781295e-4,
317
            -5.952379913043012e-4,
318
            7.93650793500350248e-4,
319
            -0.002777777777777681622553,
320
            0.08333333333333333331554247,
321
            0.0057083835261
322
        );
323
324
        // Rough estimate of the fourth root of logGamma_xBig
325
        static $lg_frtbig = 2.25e76;
326
        static $pnt68     = 0.6796875;
327
328
329
        if ($x == self::$logGammaCacheX) {
330
            return self::$logGammaCacheResult;
331
        }
332
        $y = $x;
333
        if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) {
334
            if ($y <= EPS) {
335
                $res = -log(y);
336
            } elseif ($y <= 1.5) {
337
                // ---------------------
338
                //    EPS .LT. X .LE. 1.5
339
                // ---------------------
340
                if ($y < $pnt68) {
341
                    $corr = -log($y);
342
                    $xm1 = $y;
343
                } else {
344
                    $corr = 0.0;
345
                    $xm1 = $y - 1.0;
346
                }
347
                if ($y <= 0.5 || $y >= $pnt68) {
348
                    $xden = 1.0;
349
                    $xnum = 0.0;
350
                    for ($i = 0; $i < 8; ++$i) {
351
                        $xnum = $xnum * $xm1 + $lg_p1[$i];
352
                        $xden = $xden * $xm1 + $lg_q1[$i];
353
                    }
354
                    $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden));
355 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...
356
                    $xm2 = $y - 1.0;
357
                    $xden = 1.0;
358
                    $xnum = 0.0;
359
                    for ($i = 0; $i < 8; ++$i) {
360
                        $xnum = $xnum * $xm2 + $lg_p2[$i];
361
                        $xden = $xden * $xm2 + $lg_q2[$i];
362
                    }
363
                    $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
364
                }
365 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...
366
                // ---------------------
367
                //    1.5 .LT. X .LE. 4.0
368
                // ---------------------
369
                $xm2 = $y - 2.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 = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
377
            } elseif ($y <= 12.0) {
378
                // ----------------------
379
                //    4.0 .LT. X .LE. 12.0
380
                // ----------------------
381
                $xm4 = $y - 4.0;
382
                $xden = -1.0;
383
                $xnum = 0.0;
384
                for ($i = 0; $i < 8; ++$i) {
385
                    $xnum = $xnum * $xm4 + $lg_p4[$i];
386
                    $xden = $xden * $xm4 + $lg_q4[$i];
387
                }
388
                $res = $lg_d4 + $xm4 * ($xnum / $xden);
389
            } else {
390
                // ---------------------------------
391
                //    Evaluate for argument .GE. 12.0
392
                // ---------------------------------
393
                $res = 0.0;
394
                if ($y <= $lg_frtbig) {
395
                    $res = $lg_c[6];
396
                    $ysq = $y * $y;
397
                    for ($i = 0; $i < 6; ++$i) {
398
                        $res = $res / $ysq + $lg_c[$i];
399
                    }
400
                    $res /= $y;
401
                    $corr = log($y);
402
                    $res = $res + log(SQRT2PI) - 0.5 * $corr;
403
                    $res += $y * ($corr - 1.0);
404
                }
405
            }
406
        } else {
407
            // --------------------------
408
            //    Return for bad arguments
409
            // --------------------------
410
            $res = MAX_VALUE;
411
        }
412
        // ------------------------------
413
        //    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...
414
        // ------------------------------
415
        self::$logGammaCacheX = $x;
416
        self::$logGammaCacheResult = $res;
417
        return $res;
418
    }
419
420
421
    //
422
    //    Private implementation of the incomplete Gamma function
423
    //
424
    private static function incompleteGamma($a, $x)
425
    {
426
        static $max = 32;
427
        $summer = 0;
428
        for ($n=0; $n<=$max; ++$n) {
429
            $divisor = $a;
430
            for ($i=1; $i<=$n; ++$i) {
431
                $divisor *= ($a + $i);
432
            }
433
            $summer += (pow($x, $n) / $divisor);
434
        }
435
        return pow($x, $a) * exp(0-$x) * $summer;
436
    }
437
438
439
    //
440
    //    Private implementation of the Gamma function
441
    //
442
    private static function gamma($data)
443
    {
444
        if ($data == 0.0) {
445
            return 0;
446
        }
447
448
        static $p0 = 1.000000000190015;
449
        static $p = array(
450
            1 => 76.18009172947146,
451
            2 => -86.50532032941677,
452
            3 => 24.01409824083091,
453
            4 => -1.231739572450155,
454
            5 => 1.208650973866179e-3,
455
            6 => -5.395239384953e-6
456
        );
457
458
        $y = $x = $data;
459
        $tmp = $x + 5.5;
460
        $tmp -= ($x + 0.5) * log($tmp);
461
462
        $summer = $p0;
463
        for ($j=1; $j<=6; ++$j) {
464
            $summer += ($p[$j] / ++$y);
465
        }
466
        return exp(0 - $tmp + log(SQRT2PI * $summer / $x));
467
    }
468
469
470
    /***************************************************************************
471
     *                                inverse_ncdf.php
472
     *                            -------------------
473
     *    begin                : Friday, January 16, 2004
474
     *    copyright            : (C) 2004 Michael Nickerson
475
     *    email                : [email protected]
476
     *
477
     ***************************************************************************/
478
    private static function inverseNcdf($p)
479
    {
480
        //    Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
481
        //    PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
482
        //    a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
483
        //    I have not checked the accuracy of this implementation. Be aware that PHP
484
        //    will truncate the coeficcients to 14 digits.
485
486
        //    You have permission to use and distribute this function freely for
487
        //    whatever purpose you want, but please show common courtesy and give credit
488
        //    where credit is due.
489
490
        //    Input paramater is $p - probability - where 0 < p < 1.
491
492
        //    Coefficients in rational approximations
493
        static $a = array(
494
            1 => -3.969683028665376e+01,
495
            2 => 2.209460984245205e+02,
496
            3 => -2.759285104469687e+02,
497
            4 => 1.383577518672690e+02,
498
            5 => -3.066479806614716e+01,
499
            6 => 2.506628277459239e+00
500
        );
501
502
        static $b = array(
503
            1 => -5.447609879822406e+01,
504
            2 => 1.615858368580409e+02,
505
            3 => -1.556989798598866e+02,
506
            4 => 6.680131188771972e+01,
507
            5 => -1.328068155288572e+01
508
        );
509
510
        static $c = array(
511
            1 => -7.784894002430293e-03,
512
            2 => -3.223964580411365e-01,
513
            3 => -2.400758277161838e+00,
514
            4 => -2.549732539343734e+00,
515
            5 => 4.374664141464968e+00,
516
            6 => 2.938163982698783e+00
517
        );
518
519
        static $d = array(
520
            1 => 7.784695709041462e-03,
521
            2 => 3.224671290700398e-01,
522
            3 => 2.445134137142996e+00,
523
            4 => 3.754408661907416e+00
524
        );
525
526
        //    Define lower and upper region break-points.
527
        $p_low = 0.02425;            //Use lower region approx. below this
528
        $p_high = 1 - $p_low;        //Use upper region approx. above this
529
530
        if (0 < $p && $p < $p_low) {
531
            //    Rational approximation for lower region.
532
            $q = sqrt(-2 * log($p));
533
            return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
534
                    (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
535
        } elseif ($p_low <= $p && $p <= $p_high) {
536
            //    Rational approximation for central region.
537
            $q = $p - 0.5;
538
            $r = $q * $q;
539
            return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q /
540
                   ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
541
        } elseif ($p_high < $p && $p < 1) {
542
            //    Rational approximation for upper region.
543
            $q = sqrt(-2 * log(1 - $p));
544
            return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
545
                     (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
546
        }
547
        //    If 0 < p < 1, return a null value
548
        return Functions::NULL();
549
    }
550
551
552
    private static function inverseNcdf2($prob)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
553
    {
554
        //    Approximation of inverse standard normal CDF developed by
555
        //    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...
556
557
        $a1 = 2.50662823884;
558
        $a2 = -18.61500062529;
559
        $a3 = 41.39119773534;
560
        $a4 = -25.44106049637;
561
562
        $b1 = -8.4735109309;
563
        $b2 = 23.08336743743;
564
        $b3 = -21.06224101826;
565
        $b4 = 3.13082909833;
566
567
        $c1 = 0.337475482272615;
568
        $c2 = 0.976169019091719;
569
        $c3 = 0.160797971491821;
570
        $c4 = 2.76438810333863E-02;
571
        $c5 = 3.8405729373609E-03;
572
        $c6 = 3.951896511919E-04;
573
        $c7 = 3.21767881768E-05;
574
        $c8 = 2.888167364E-07;
575
        $c9 = 3.960315187E-07;
576
577
        $y = $prob - 0.5;
578
        if (abs($y) < 0.42) {
579
            $z = ($y * $y);
580
            $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1);
581
        } else {
582
            if ($y > 0) {
583
                $z = log(-log(1 - $prob));
584
            } else {
585
                $z = log(-log($prob));
586
            }
587
            $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9)))))));
588
            if ($y < 0) {
589
                $z = -$z;
590
            }
591
        }
592
        return $z;
593
    }    //    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...
594
595
596
    private static function inverseNcdf3($p)
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
597
    {
598
        //    ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3.
599
        //    Produces the normal deviate Z corresponding to a given lower
600
        //    tail area of P; Z is accurate to about 1 part in 10**16.
601
        //
602
        //    This is a PHP version of the original FORTRAN code that can
603
        //    be found at http://lib.stat.cmu.edu/apstat/
604
        $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...
605
        $split2 = 5;
606
        $const1 = 0.180625;
607
        $const2 = 1.6;
608
609
        //    coefficients for p close to 0.5
610
        $a0 = 3.3871328727963666080;
611
        $a1 = 1.3314166789178437745E+2;
612
        $a2 = 1.9715909503065514427E+3;
613
        $a3 = 1.3731693765509461125E+4;
614
        $a4 = 4.5921953931549871457E+4;
615
        $a5 = 6.7265770927008700853E+4;
616
        $a6 = 3.3430575583588128105E+4;
617
        $a7 = 2.5090809287301226727E+3;
618
619
        $b1 = 4.2313330701600911252E+1;
620
        $b2 = 6.8718700749205790830E+2;
621
        $b3 = 5.3941960214247511077E+3;
622
        $b4 = 2.1213794301586595867E+4;
623
        $b5 = 3.9307895800092710610E+4;
624
        $b6 = 2.8729085735721942674E+4;
625
        $b7 = 5.2264952788528545610E+3;
626
627
        //    coefficients for p not close to 0, 0.5 or 1.
628
        $c0 = 1.42343711074968357734;
629
        $c1 = 4.63033784615654529590;
630
        $c2 = 5.76949722146069140550;
631
        $c3 = 3.64784832476320460504;
632
        $c4 = 1.27045825245236838258;
633
        $c5 = 2.41780725177450611770E-1;
634
        $c6 = 2.27238449892691845833E-2;
635
        $c7 = 7.74545014278341407640E-4;
636
637
        $d1 = 2.05319162663775882187;
638
        $d2 = 1.67638483018380384940;
639
        $d3 = 6.89767334985100004550E-1;
640
        $d4 = 1.48103976427480074590E-1;
641
        $d5 = 1.51986665636164571966E-2;
642
        $d6 = 5.47593808499534494600E-4;
643
        $d7 = 1.05075007164441684324E-9;
644
645
        //    coefficients for p near 0 or 1.
646
        $e0 = 6.65790464350110377720;
647
        $e1 = 5.46378491116411436990;
648
        $e2 = 1.78482653991729133580;
649
        $e3 = 2.96560571828504891230E-1;
650
        $e4 = 2.65321895265761230930E-2;
651
        $e5 = 1.24266094738807843860E-3;
652
        $e6 = 2.71155556874348757815E-5;
653
        $e7 = 2.01033439929228813265E-7;
654
655
        $f1 = 5.99832206555887937690E-1;
656
        $f2 = 1.36929880922735805310E-1;
657
        $f3 = 1.48753612908506148525E-2;
658
        $f4 = 7.86869131145613259100E-4;
659
        $f5 = 1.84631831751005468180E-5;
660
        $f6 = 1.42151175831644588870E-7;
661
        $f7 = 2.04426310338993978564E-15;
662
663
        $q = $p - 0.5;
664
665
        //    computation for p close to 0.5
666
        if (abs($q) <= split1) {
667
            $R = $const1 - $q * $q;
668
            $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) /
669
                      ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1);
670
        } else {
671
            if ($q < 0) {
672
                $R = $p;
673
            } else {
674
                $R = 1 - $p;
675
            }
676
            $R = pow(-log($R), 2);
677
678
            //    computation for p not close to 0, 0.5 or 1.
679
            if ($R <= $split2) {
680
                $R = $R - $const2;
681
                $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) /
682
                     ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1);
683
            } else {
684
            //    computation for p near 0 or 1.
685
                $R = $R - $split2;
686
                $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) /
687
                     ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1);
688
            }
689
            if ($q < 0) {
690
                $z = -$z;
691
            }
692
        }
693
        return $z;
694
    }
695
696
697
    /**
698
     * AVEDEV
699
     *
700
     * Returns the average of the absolute deviations of data points from their mean.
701
     * AVEDEV is a measure of the variability in a data set.
702
     *
703
     * Excel Function:
704
     *        AVEDEV(value1[,value2[, ...]])
705
     *
706
     * @access    public
707
     * @category Statistical Functions
708
     * @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...
709
     * @return    float
710
     */
711 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...
712
    {
713
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
714
715
        // Return value
716
        $returnValue = null;
717
718
        $aMean = self::AVERAGE($aArgs);
719
        if ($aMean != Functions::DIV0()) {
720
            $aCount = 0;
721
            foreach ($aArgs as $k => $arg) {
722
                if ((is_bool($arg)) &&
723
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
724
                    $arg = (integer) $arg;
725
                }
726
                // Is it a numeric value?
727
                if ((is_numeric($arg)) && (!is_string($arg))) {
728
                    if (is_null($returnValue)) {
729
                        $returnValue = abs($arg - $aMean);
730
                    } else {
731
                        $returnValue += abs($arg - $aMean);
732
                    }
733
                    ++$aCount;
734
                }
735
            }
736
737
            // Return
738
            if ($aCount == 0) {
739
                return Functions::DIV0();
740
            }
741
            return $returnValue / $aCount;
742
        }
743
        return Functions::NAN();
744
    }
745
746
747
    /**
748
     * AVERAGE
749
     *
750
     * Returns the average (arithmetic mean) of the arguments
751
     *
752
     * Excel Function:
753
     *        AVERAGE(value1[,value2[, ...]])
754
     *
755
     * @access    public
756
     * @category Statistical Functions
757
     * @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...
758
     * @return    float
759
     */
760
    public static function AVERAGE()
761
    {
762
        $returnValue = $aCount = 0;
763
764
        // Loop through arguments
765
        foreach (Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
766
            if ((is_bool($arg)) &&
767
                ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
768
                $arg = (integer) $arg;
769
            }
770
            // Is it a numeric value?
771
            if ((is_numeric($arg)) && (!is_string($arg))) {
772
                if (is_null($returnValue)) {
773
                    $returnValue = $arg;
774
                } else {
775
                    $returnValue += $arg;
776
                }
777
                ++$aCount;
778
            }
779
        }
780
781
        // Return
782
        if ($aCount > 0) {
783
            return $returnValue / $aCount;
784
        } else {
785
            return Functions::DIV0();
786
        }
787
    }
788
789
790
    /**
791
     * AVERAGEA
792
     *
793
     * Returns the average of its arguments, including numbers, text, and logical values
794
     *
795
     * Excel Function:
796
     *        AVERAGEA(value1[,value2[, ...]])
797
     *
798
     * @access    public
799
     * @category Statistical Functions
800
     * @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...
801
     * @return    float
802
     */
803
    public static function AVERAGEA()
804
    {
805
        $returnValue = null;
806
807
        $aCount = 0;
808
        // Loop through arguments
809
        foreach (Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
810
            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...
811
                (!Functions::isMatrixValue($k))) {
812
            } else {
813
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
814
                    if (is_bool($arg)) {
815
                        $arg = (integer) $arg;
816
                    } elseif (is_string($arg)) {
817
                        $arg = 0;
818
                    }
819
                    if (is_null($returnValue)) {
820
                        $returnValue = $arg;
821
                    } else {
822
                        $returnValue += $arg;
823
                    }
824
                    ++$aCount;
825
                }
826
            }
827
        }
828
829
        if ($aCount > 0) {
830
            return $returnValue / $aCount;
831
        } else {
832
            return Functions::DIV0();
833
        }
834
    }
835
836
837
    /**
838
     * AVERAGEIF
839
     *
840
     * Returns the average value from a range of cells that contain numbers within the list of arguments
841
     *
842
     * Excel Function:
843
     *        AVERAGEIF(value1[,value2[, ...]],condition)
844
     *
845
     * @access    public
846
     * @category Mathematical and Trigonometric Functions
847
     * @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...
848
     * @param    string        $condition        The criteria that defines which cells will be checked.
849
     * @param    mixed[]        $averageArgs    Data values
850
     * @return    float
851
     */
852
    public static function AVERAGEIF($aArgs, $condition, $averageArgs = array())
853
    {
854
        $returnValue = 0;
855
856
        $aArgs = Functions::flattenArray($aArgs);
857
        $averageArgs = Functions::flattenArray($averageArgs);
858
        if (empty($averageArgs)) {
859
            $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...
860
        }
861
        $condition = Functions::ifCondition($condition);
862
        // Loop through arguments
863
        $aCount = 0;
864
        foreach ($aArgs as $key => $arg) {
865
            if (!is_numeric($arg)) {
866
                $arg = \PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
867
            }
868
            $testCondition = '='.$arg.$condition;
869
            if (\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
870
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
871
                    $returnValue += $arg;
872
                    ++$aCount;
873
                }
874
            }
875
        }
876
877
        if ($aCount > 0) {
878
            return $returnValue / $aCount;
879
        }
880
        return Functions::DIV0();
881
    }
882
883
884
    /**
885
     * BETADIST
886
     *
887
     * Returns the beta distribution.
888
     *
889
     * @param    float        $value            Value at which you want to evaluate the distribution
890
     * @param    float        $alpha            Parameter to the distribution
891
     * @param    float        $beta            Parameter to the distribution
892
     * @param    boolean        $cumulative
0 ignored issues
show
Bug introduced by
There is no parameter named $cumulative. 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...
893
     * @return    float
894
     *
895
     */
896
    public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1)
897
    {
898
        $value = Functions::flattenSingleValue($value);
899
        $alpha = Functions::flattenSingleValue($alpha);
900
        $beta  = Functions::flattenSingleValue($beta);
901
        $rMin  = Functions::flattenSingleValue($rMin);
902
        $rMax  = Functions::flattenSingleValue($rMax);
903
904
        if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
905
            if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) {
906
                return Functions::NAN();
907
            }
908
            if ($rMin > $rMax) {
909
                $tmp = $rMin;
910
                $rMin = $rMax;
911
                $rMax = $tmp;
912
            }
913
            $value -= $rMin;
914
            $value /= ($rMax - $rMin);
915
            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<PhpSpreadsheet\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<PhpSpreadsheet\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<PhpSpreadsheet\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...
916
        }
917
        return Functions::VALUE();
918
    }
919
920
921
    /**
922
     * BETAINV
923
     *
924
     * Returns the inverse of the beta distribution.
925
     *
926
     * @param    float        $probability    Probability at which you want to evaluate the distribution
927
     * @param    float        $alpha            Parameter to the distribution
928
     * @param    float        $beta            Parameter to the distribution
929
     * @param    float        $rMin            Minimum value
930
     * @param    float        $rMax            Maximum value
931
     * @param    boolean        $cumulative
0 ignored issues
show
Bug introduced by
There is no parameter named $cumulative. 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...
932
     * @return    float
933
     *
934
     */
935
    public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1)
936
    {
937
        $probability = Functions::flattenSingleValue($probability);
938
        $alpha       = Functions::flattenSingleValue($alpha);
939
        $beta        = Functions::flattenSingleValue($beta);
940
        $rMin        = Functions::flattenSingleValue($rMin);
941
        $rMax        = Functions::flattenSingleValue($rMax);
942
943
        if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
944 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...
945
                return Functions::NAN();
946
            }
947
            if ($rMin > $rMax) {
948
                $tmp = $rMin;
949
                $rMin = $rMax;
950
                $rMax = $tmp;
951
            }
952
            $a = 0;
953
            $b = 2;
954
955
            $i = 0;
956
            while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
957
                $guess = ($a + $b) / 2;
958
                $result = self::BETADIST($guess, $alpha, $beta);
959
                if (($result == $probability) || ($result == 0)) {
960
                    $b = $a;
961
                } elseif ($result > $probability) {
962
                    $b = $guess;
963
                } else {
964
                    $a = $guess;
965
                }
966
            }
967
            if ($i == MAX_ITERATIONS) {
968
                return Functions::NA();
969
            }
970
            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...
971
        }
972
        return Functions::VALUE();
973
    }
974
975
976
    /**
977
     * BINOMDIST
978
     *
979
     * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
980
     *        a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
981
     *        when trials are independent, and when the probability of success is constant throughout the
982
     *        experiment. For example, BINOMDIST can calculate the probability that two of the next three
983
     *        babies born are male.
984
     *
985
     * @param    float        $value            Number of successes in trials
986
     * @param    float        $trials            Number of trials
987
     * @param    float        $probability    Probability of success on each trial
988
     * @param    boolean        $cumulative
989
     * @return    float
990
     *
991
     * @todo    Cumulative distribution function
992
     *
993
     */
994
    public static function BINOMDIST($value, $trials, $probability, $cumulative)
995
    {
996
        $value       = floor(Functions::flattenSingleValue($value));
997
        $trials      = floor(Functions::flattenSingleValue($trials));
998
        $probability = Functions::flattenSingleValue($probability);
999
1000
        if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) {
1001
            if (($value < 0) || ($value > $trials)) {
1002
                return Functions::NAN();
1003
            }
1004
            if (($probability < 0) || ($probability > 1)) {
1005
                return Functions::NAN();
1006
            }
1007
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1008
                if ($cumulative) {
1009
                    $summer = 0;
1010
                    for ($i = 0; $i <= $value; ++$i) {
1011
                        $summer += MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i);
1012
                    }
1013
                    return $summer;
1014
                } else {
1015
                    return MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value) ;
1016
                }
1017
            }
1018
        }
1019
        return Functions::VALUE();
1020
    }
1021
1022
1023
    /**
1024
     * CHIDIST
1025
     *
1026
     * Returns the one-tailed probability of the chi-squared distribution.
1027
     *
1028
     * @param    float        $value            Value for the function
1029
     * @param    float        $degrees        degrees of freedom
1030
     * @return    float
1031
     */
1032
    public static function CHIDIST($value, $degrees)
1033
    {
1034
        $value   = Functions::flattenSingleValue($value);
1035
        $degrees = floor(Functions::flattenSingleValue($degrees));
1036
1037
        if ((is_numeric($value)) && (is_numeric($degrees))) {
1038
            if ($degrees < 1) {
1039
                return Functions::NAN();
1040
            }
1041
            if ($value < 0) {
1042
                if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1043
                    return 1;
1044
                }
1045
                return Functions::NAN();
1046
            }
1047
            return 1 - (self::incompleteGamma($degrees/2, $value/2) / self::gamma($degrees/2));
1048
        }
1049
        return Functions::VALUE();
1050
    }
1051
1052
1053
    /**
1054
     * CHIINV
1055
     *
1056
     * Returns the one-tailed probability of the chi-squared distribution.
1057
     *
1058
     * @param    float        $probability    Probability for the function
1059
     * @param    float        $degrees        degrees of freedom
1060
     * @return    float
1061
     */
1062 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...
1063
    {
1064
        $probability = Functions::flattenSingleValue($probability);
1065
        $degrees     = floor(Functions::flattenSingleValue($degrees));
1066
1067
        if ((is_numeric($probability)) && (is_numeric($degrees))) {
1068
            $xLo = 100;
1069
            $xHi = 0;
1070
1071
            $x = $xNew = 1;
1072
            $dx    = 1;
1073
            $i = 0;
1074
1075
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1076
                // Apply Newton-Raphson step
1077
                $result = self::CHIDIST($x, $degrees);
1078
                $error = $result - $probability;
1079
                if ($error == 0.0) {
1080
                    $dx = 0;
1081
                } elseif ($error < 0.0) {
1082
                    $xLo = $x;
1083
                } else {
1084
                    $xHi = $x;
1085
                }
1086
                // Avoid division by zero
1087
                if ($result != 0.0) {
1088
                    $dx = $error / $result;
1089
                    $xNew = $x - $dx;
1090
                }
1091
                // If the NR fails to converge (which for example may be the
1092
                // case if the initial guess is too rough) we apply a bisection
1093
                // step to determine a more narrow interval around the root.
1094
                if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
1095
                    $xNew = ($xLo + $xHi) / 2;
1096
                    $dx = $xNew - $x;
1097
                }
1098
                $x = $xNew;
1099
            }
1100
            if ($i == MAX_ITERATIONS) {
1101
                return Functions::NA();
1102
            }
1103
            return round($x, 12);
1104
        }
1105
        return Functions::VALUE();
1106
    }
1107
1108
1109
    /**
1110
     * CONFIDENCE
1111
     *
1112
     * Returns the confidence interval for a population mean
1113
     *
1114
     * @param    float        $alpha
1115
     * @param    float        $stdDev        Standard Deviation
1116
     * @param    float        $size
1117
     * @return    float
1118
     *
1119
     */
1120
    public static function CONFIDENCE($alpha, $stdDev, $size)
1121
    {
1122
        $alpha  = Functions::flattenSingleValue($alpha);
1123
        $stdDev = Functions::flattenSingleValue($stdDev);
1124
        $size   = floor(Functions::flattenSingleValue($size));
1125
1126
        if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) {
1127
            if (($alpha <= 0) || ($alpha >= 1)) {
1128
                return Functions::NAN();
1129
            }
1130
            if (($stdDev <= 0) || ($size < 1)) {
1131
                return Functions::NAN();
1132
            }
1133
            return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size);
1134
        }
1135
        return Functions::VALUE();
1136
    }
1137
1138
1139
    /**
1140
     * CORREL
1141
     *
1142
     * Returns covariance, the average of the products of deviations for each data point pair.
1143
     *
1144
     * @param    array of mixed        Data Series Y
1145
     * @param    array of mixed        Data Series X
1146
     * @return    float
1147
     */
1148
    public static function CORREL($yValues, $xValues = null)
1149
    {
1150
        if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) {
1151
            return Functions::VALUE();
1152
        }
1153
        if (!self::checkTrendArrays($yValues, $xValues)) {
1154
            return Functions::VALUE();
1155
        }
1156
        $yValueCount = count($yValues);
1157
        $xValueCount = count($xValues);
1158
1159
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1160
            return Functions::NA();
1161
        } elseif ($yValueCount == 1) {
1162
            return Functions::DIV0();
1163
        }
1164
1165
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1166
        return $bestFitLinear->getCorrelation();
1167
    }
1168
1169
1170
    /**
1171
     * COUNT
1172
     *
1173
     * Counts the number of cells that contain numbers within the list of arguments
1174
     *
1175
     * Excel Function:
1176
     *        COUNT(value1[,value2[, ...]])
1177
     *
1178
     * @access    public
1179
     * @category Statistical Functions
1180
     * @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...
1181
     * @return    int
1182
     */
1183
    public static function COUNT()
1184
    {
1185
        $returnValue = 0;
1186
1187
        // Loop through arguments
1188
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1189
        foreach ($aArgs as $k => $arg) {
1190
            if ((is_bool($arg)) &&
1191
                ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
1192
                $arg = (integer) $arg;
1193
            }
1194
            // Is it a numeric value?
1195
            if ((is_numeric($arg)) && (!is_string($arg))) {
1196
                ++$returnValue;
1197
            }
1198
        }
1199
1200
        return $returnValue;
1201
    }
1202
1203
1204
    /**
1205
     * COUNTA
1206
     *
1207
     * Counts the number of cells that are not empty within the list of arguments
1208
     *
1209
     * Excel Function:
1210
     *        COUNTA(value1[,value2[, ...]])
1211
     *
1212
     * @access    public
1213
     * @category Statistical Functions
1214
     * @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...
1215
     * @return    int
1216
     */
1217 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...
1218
    {
1219
        $returnValue = 0;
1220
1221
        // Loop through arguments
1222
        $aArgs = Functions::flattenArray(func_get_args());
1223
        foreach ($aArgs as $arg) {
1224
            // Is it a numeric, boolean or string value?
1225
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
1226
                ++$returnValue;
1227
            }
1228
        }
1229
1230
        return $returnValue;
1231
    }
1232
1233
1234
    /**
1235
     * COUNTBLANK
1236
     *
1237
     * Counts the number of empty cells within the list of arguments
1238
     *
1239
     * Excel Function:
1240
     *        COUNTBLANK(value1[,value2[, ...]])
1241
     *
1242
     * @access    public
1243
     * @category Statistical Functions
1244
     * @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...
1245
     * @return    int
1246
     */
1247 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...
1248
    {
1249
        $returnValue = 0;
1250
1251
        // Loop through arguments
1252
        $aArgs = Functions::flattenArray(func_get_args());
1253
        foreach ($aArgs as $arg) {
1254
            // Is it a blank cell?
1255
            if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
1256
                ++$returnValue;
1257
            }
1258
        }
1259
1260
        return $returnValue;
1261
    }
1262
1263
1264
    /**
1265
     * COUNTIF
1266
     *
1267
     * Counts the number of cells that contain numbers within the list of arguments
1268
     *
1269
     * Excel Function:
1270
     *        COUNTIF(value1[,value2[, ...]],condition)
1271
     *
1272
     * @access    public
1273
     * @category Statistical Functions
1274
     * @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...
1275
     * @param    string        $condition        The criteria that defines which cells will be counted.
1276
     * @return    int
1277
     */
1278
    public static function COUNTIF($aArgs, $condition)
1279
    {
1280
        $returnValue = 0;
1281
1282
        $aArgs = Functions::flattenArray($aArgs);
1283
        $condition = Functions::ifCondition($condition);
1284
        // Loop through arguments
1285
        foreach ($aArgs as $arg) {
1286
            if (!is_numeric($arg)) {
1287
                $arg = \PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
1288
            }
1289
            $testCondition = '='.$arg.$condition;
1290
            if (\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1291
                // Is it a value within our criteria
1292
                ++$returnValue;
1293
            }
1294
        }
1295
1296
        return $returnValue;
1297
    }
1298
1299
1300
    /**
1301
     * COVAR
1302
     *
1303
     * Returns covariance, the average of the products of deviations for each data point pair.
1304
     *
1305
     * @param    array of mixed        Data Series Y
1306
     * @param    array of mixed        Data Series X
1307
     * @return    float
1308
     */
1309 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...
1310
    {
1311
        if (!self::checkTrendArrays($yValues, $xValues)) {
1312
            return Functions::VALUE();
1313
        }
1314
        $yValueCount = count($yValues);
1315
        $xValueCount = count($xValues);
1316
1317
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1318
            return Functions::NA();
1319
        } elseif ($yValueCount == 1) {
1320
            return Functions::DIV0();
1321
        }
1322
1323
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1324
        return $bestFitLinear->getCovariance();
1325
    }
1326
1327
1328
    /**
1329
     * CRITBINOM
1330
     *
1331
     * Returns the smallest value for which the cumulative binomial distribution is greater
1332
     *        than or equal to a criterion value
1333
     *
1334
     * See http://support.microsoft.com/kb/828117/ for details of the algorithm used
1335
     *
1336
     * @param    float        $trials            number of Bernoulli trials
1337
     * @param    float        $probability    probability of a success on each trial
1338
     * @param    float        $alpha            criterion value
1339
     * @return    int
1340
     *
1341
     * @todo    Warning. This implementation differs from the algorithm detailed on the MS
1342
     *            web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess
1343
     *            This eliminates a potential endless loop error, but may have an adverse affect on the
1344
     *            accuracy of the function (although all my tests have so far returned correct results).
1345
     *
1346
     */
1347
    public static function CRITBINOM($trials, $probability, $alpha)
1348
    {
1349
        $trials      = floor(Functions::flattenSingleValue($trials));
1350
        $probability = Functions::flattenSingleValue($probability);
1351
        $alpha       = Functions::flattenSingleValue($alpha);
1352
1353
        if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) {
1354
            if ($trials < 0) {
1355
                return Functions::NAN();
1356
            } elseif (($probability < 0) || ($probability > 1)) {
1357
                return Functions::NAN();
1358
            } elseif (($alpha < 0) || ($alpha > 1)) {
1359
                return Functions::NAN();
1360
            } elseif ($alpha <= 0.5) {
1361
                $t = sqrt(log(1 / ($alpha * $alpha)));
1362
                $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));
1363
            } else {
1364
                $t = sqrt(log(1 / pow(1 - $alpha, 2)));
1365
                $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t);
1366
            }
1367
            $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability)));
1368
            if ($Guess < 0) {
1369
                $Guess = 0;
1370
            } elseif ($Guess > $trials) {
1371
                $Guess = $trials;
1372
            }
1373
1374
            $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0;
1375
            $EssentiallyZero = 10e-12;
1376
1377
            $m = floor($trials * $probability);
1378
            ++$TotalUnscaledProbability;
1379
            if ($m == $Guess) {
1380
                ++$UnscaledPGuess;
1381
            }
1382
            if ($m <= $Guess) {
1383
                ++$UnscaledCumPGuess;
1384
            }
1385
1386
            $PreviousValue = 1;
1387
            $Done = false;
1388
            $k = $m + 1;
1389 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...
1390
                $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability));
1391
                $TotalUnscaledProbability += $CurrentValue;
1392
                if ($k == $Guess) {
1393
                    $UnscaledPGuess += $CurrentValue;
1394
                }
1395
                if ($k <= $Guess) {
1396
                    $UnscaledCumPGuess += $CurrentValue;
1397
                }
1398
                if ($CurrentValue <= $EssentiallyZero) {
1399
                    $Done = true;
1400
                }
1401
                $PreviousValue = $CurrentValue;
1402
                ++$k;
1403
            }
1404
1405
            $PreviousValue = 1;
1406
            $Done = false;
1407
            $k = $m - 1;
1408 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...
1409
                $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability);
1410
                $TotalUnscaledProbability += $CurrentValue;
1411
                if ($k == $Guess) {
1412
                    $UnscaledPGuess += $CurrentValue;
1413
                }
1414
                if ($k <= $Guess) {
1415
                    $UnscaledCumPGuess += $CurrentValue;
1416
                }
1417
                if ($CurrentValue <= $EssentiallyZero) {
1418
                    $Done = true;
1419
                }
1420
                $PreviousValue = $CurrentValue;
1421
                --$k;
1422
            }
1423
1424
            $PGuess = $UnscaledPGuess / $TotalUnscaledProbability;
1425
            $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability;
1426
1427
//            $CumPGuessMinus1 = $CumPGuess - $PGuess;
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
1428
            $CumPGuessMinus1 = $CumPGuess - 1;
1429
1430
            while (true) {
1431
                if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) {
1432
                    return $Guess;
1433
                } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) {
1434
                    $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability);
1435
                    $CumPGuessMinus1 = $CumPGuess;
1436
                    $CumPGuess = $CumPGuess + $PGuessPlus1;
1437
                    $PGuess = $PGuessPlus1;
1438
                    ++$Guess;
1439
                } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) {
1440
                    $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability;
1441
                    $CumPGuess = $CumPGuessMinus1;
1442
                    $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess;
1443
                    $PGuess = $PGuessMinus1;
1444
                    --$Guess;
1445
                }
1446
            }
1447
        }
1448
        return Functions::VALUE();
1449
    }
1450
1451
1452
    /**
1453
     * DEVSQ
1454
     *
1455
     * Returns the sum of squares of deviations of data points from their sample mean.
1456
     *
1457
     * Excel Function:
1458
     *        DEVSQ(value1[,value2[, ...]])
1459
     *
1460
     * @access    public
1461
     * @category Statistical Functions
1462
     * @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...
1463
     * @return    float
1464
     */
1465 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...
1466
    {
1467
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1468
1469
        // Return value
1470
        $returnValue = null;
1471
1472
        $aMean = self::AVERAGE($aArgs);
1473
        if ($aMean != Functions::DIV0()) {
1474
            $aCount = -1;
1475
            foreach ($aArgs as $k => $arg) {
1476
                // Is it a numeric value?
1477
                if ((is_bool($arg)) &&
1478
                    ((!Functions::isCellValue($k)) ||
1479
                    (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
1480
                    $arg = (integer) $arg;
1481
                }
1482
                if ((is_numeric($arg)) && (!is_string($arg))) {
1483
                    if (is_null($returnValue)) {
1484
                        $returnValue = pow(($arg - $aMean), 2);
1485
                    } else {
1486
                        $returnValue += pow(($arg - $aMean), 2);
1487
                    }
1488
                    ++$aCount;
1489
                }
1490
            }
1491
1492
            // Return
1493
            if (is_null($returnValue)) {
1494
                return Functions::NAN();
1495
            } else {
1496
                return $returnValue;
1497
            }
1498
        }
1499
        return self::NA();
0 ignored issues
show
Bug introduced by
The method NA() does not seem to exist on object<PhpSpreadsheet\Calculation\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...
1500
    }
1501
1502
1503
    /**
1504
     * EXPONDIST
1505
     *
1506
     *    Returns the exponential distribution. Use EXPONDIST to model the time between events,
1507
     *        such as how long an automated bank teller takes to deliver cash. For example, you can
1508
     *        use EXPONDIST to determine the probability that the process takes at most 1 minute.
1509
     *
1510
     * @param    float        $value            Value of the function
1511
     * @param    float        $lambda            The parameter value
1512
     * @param    boolean        $cumulative
1513
     * @return    float
1514
     */
1515
    public static function EXPONDIST($value, $lambda, $cumulative)
1516
    {
1517
        $value    = Functions::flattenSingleValue($value);
1518
        $lambda    = Functions::flattenSingleValue($lambda);
1519
        $cumulative    = Functions::flattenSingleValue($cumulative);
1520
1521
        if ((is_numeric($value)) && (is_numeric($lambda))) {
1522
            if (($value < 0) || ($lambda < 0)) {
1523
                return Functions::NAN();
1524
            }
1525
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1526
                if ($cumulative) {
1527
                    return 1 - exp(0-$value*$lambda);
1528
                } else {
1529
                    return $lambda * exp(0-$value*$lambda);
1530
                }
1531
            }
1532
        }
1533
        return Functions::VALUE();
1534
    }
1535
1536
1537
    /**
1538
     * FISHER
1539
     *
1540
     * Returns the Fisher transformation at x. This transformation produces a function that
1541
     *        is normally distributed rather than skewed. Use this function to perform hypothesis
1542
     *        testing on the correlation coefficient.
1543
     *
1544
     * @param    float        $value
1545
     * @return    float
1546
     */
1547
    public static function FISHER($value)
1548
    {
1549
        $value    = Functions::flattenSingleValue($value);
1550
1551
        if (is_numeric($value)) {
1552
            if (($value <= -1) || ($value >= 1)) {
1553
                return Functions::NAN();
1554
            }
1555
            return 0.5 * log((1+$value)/(1-$value));
1556
        }
1557
        return Functions::VALUE();
1558
    }
1559
1560
1561
    /**
1562
     * FISHERINV
1563
     *
1564
     * Returns the inverse of the Fisher transformation. Use this transformation when
1565
     *        analyzing correlations between ranges or arrays of data. If y = FISHER(x), then
1566
     *        FISHERINV(y) = x.
1567
     *
1568
     * @param    float        $value
1569
     * @return    float
1570
     */
1571
    public static function FISHERINV($value)
1572
    {
1573
        $value    = Functions::flattenSingleValue($value);
1574
1575
        if (is_numeric($value)) {
1576
            return (exp(2 * $value) - 1) / (exp(2 * $value) + 1);
1577
        }
1578
        return Functions::VALUE();
1579
    }
1580
1581
1582
    /**
1583
     * FORECAST
1584
     *
1585
     * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
1586
     *
1587
     * @param    float                Value of X for which we want to find Y
1588
     * @param    array of mixed        Data Series Y
1589
     * @param    array of mixed        Data Series X
1590
     * @return    float
1591
     */
1592
    public static function FORECAST($xValue, $yValues, $xValues)
1593
    {
1594
        $xValue    = Functions::flattenSingleValue($xValue);
1595
        if (!is_numeric($xValue)) {
1596
            return Functions::VALUE();
1597
        } elseif (!self::checkTrendArrays($yValues, $xValues)) {
1598
            return Functions::VALUE();
1599
        }
1600
        $yValueCount = count($yValues);
1601
        $xValueCount = count($xValues);
1602
1603
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1604
            return Functions::NA();
1605
        } elseif ($yValueCount == 1) {
1606
            return Functions::DIV0();
1607
        }
1608
1609
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1610
        return $bestFitLinear->getValueOfYForX($xValue);
1611
    }
1612
1613
1614
    /**
1615
     * GAMMADIST
1616
     *
1617
     * Returns the gamma distribution.
1618
     *
1619
     * @param    float        $value            Value at which you want to evaluate the distribution
1620
     * @param    float        $a                Parameter to the distribution
1621
     * @param    float        $b                Parameter to the distribution
1622
     * @param    boolean        $cumulative
1623
     * @return    float
1624
     *
1625
     */
1626
    public static function GAMMADIST($value, $a, $b, $cumulative)
1627
    {
1628
        $value = Functions::flattenSingleValue($value);
1629
        $a     = Functions::flattenSingleValue($a);
1630
        $b     = Functions::flattenSingleValue($b);
1631
1632
        if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) {
1633
            if (($value < 0) || ($a <= 0) || ($b <= 0)) {
1634
                return Functions::NAN();
1635
            }
1636
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
1637
                if ($cumulative) {
1638
                    return self::incompleteGamma($a, $value / $b) / self::gamma($a);
1639
                } else {
1640
                    return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a-1) * exp(0-($value / $b));
1641
                }
1642
            }
1643
        }
1644
        return Functions::VALUE();
1645
    }
1646
1647
1648
    /**
1649
     * GAMMAINV
1650
     *
1651
     * Returns the inverse of the beta distribution.
1652
     *
1653
     * @param    float        $probability    Probability at which you want to evaluate the distribution
1654
     * @param    float        $alpha            Parameter to the distribution
1655
     * @param    float        $beta            Parameter to the distribution
1656
     * @return    float
1657
     *
1658
     */
1659
    public static function GAMMAINV($probability, $alpha, $beta)
1660
    {
1661
        $probability = Functions::flattenSingleValue($probability);
1662
        $alpha       = Functions::flattenSingleValue($alpha);
1663
        $beta        = Functions::flattenSingleValue($beta);
1664
1665
        if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) {
1666 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...
1667
                return Functions::NAN();
1668
            }
1669
1670
            $xLo = 0;
1671
            $xHi = $alpha * $beta * 5;
1672
1673
            $x = $xNew = 1;
1674
            $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...
1675
            $dx    = 1024;
1676
            $i = 0;
1677
1678
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
1679
                // Apply Newton-Raphson step
1680
                $error = self::GAMMADIST($x, $alpha, $beta, true) - $probability;
1681
                if ($error < 0.0) {
1682
                    $xLo = $x;
1683
                } else {
1684
                    $xHi = $x;
1685
                }
1686
                $pdf = self::GAMMADIST($x, $alpha, $beta, false);
1687
                // Avoid division by zero
1688
                if ($pdf != 0.0) {
1689
                    $dx = $error / $pdf;
1690
                    $xNew = $x - $dx;
1691
                }
1692
                // If the NR fails to converge (which for example may be the
1693
                // case if the initial guess is too rough) we apply a bisection
1694
                // step to determine a more narrow interval around the root.
1695
                if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) {
1696
                    $xNew = ($xLo + $xHi) / 2;
1697
                    $dx = $xNew - $x;
1698
                }
1699
                $x = $xNew;
1700
            }
1701
            if ($i == MAX_ITERATIONS) {
1702
                return Functions::NA();
1703
            }
1704
            return $x;
1705
        }
1706
        return Functions::VALUE();
1707
    }
1708
1709
1710
    /**
1711
     * GAMMALN
1712
     *
1713
     * Returns the natural logarithm of the gamma function.
1714
     *
1715
     * @param    float        $value
1716
     * @return    float
1717
     */
1718 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...
1719
    {
1720
        $value    = Functions::flattenSingleValue($value);
1721
1722
        if (is_numeric($value)) {
1723
            if ($value <= 0) {
1724
                return Functions::NAN();
1725
            }
1726
            return log(self::gamma($value));
1727
        }
1728
        return Functions::VALUE();
1729
    }
1730
1731
1732
    /**
1733
     * GEOMEAN
1734
     *
1735
     * Returns the geometric mean of an array or range of positive data. For example, you
1736
     *        can use GEOMEAN to calculate average growth rate given compound interest with
1737
     *        variable rates.
1738
     *
1739
     * Excel Function:
1740
     *        GEOMEAN(value1[,value2[, ...]])
1741
     *
1742
     * @access    public
1743
     * @category Statistical Functions
1744
     * @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...
1745
     * @return    float
1746
     */
1747
    public static function GEOMEAN()
1748
    {
1749
        $aArgs = Functions::flattenArray(func_get_args());
1750
1751
        $aMean = MathTrig::PRODUCT($aArgs);
1752
        if (is_numeric($aMean) && ($aMean > 0)) {
1753
            $aCount = self::COUNT($aArgs) ;
1754
            if (self::MIN($aArgs) > 0) {
1755
                return pow($aMean, (1 / $aCount));
1756
            }
1757
        }
1758
        return Functions::NAN();
1759
    }
1760
1761
1762
    /**
1763
     * GROWTH
1764
     *
1765
     * Returns values along a predicted emponential Trend
1766
     *
1767
     * @param    array of mixed        Data Series Y
1768
     * @param    array of mixed        Data Series X
1769
     * @param    array of mixed        Values of X for which we want to find Y
1770
     * @param    boolean                A logical value specifying whether to force the intersect to equal 0.
1771
     * @return    array of float
1772
     */
1773 View Code Duplication
    public static function GROWTH($yValues, $xValues = array(), $newValues = array(), $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...
1774
    {
1775
        $yValues = Functions::flattenArray($yValues);
1776
        $xValues = Functions::flattenArray($xValues);
1777
        $newValues = Functions::flattenArray($newValues);
1778
        $const = (is_null($const)) ? true : (boolean) Functions::flattenSingleValue($const);
1779
1780
        $bestFitExponential = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_EXPONENTIAL, $yValues, $xValues, $const);
1781
        if (empty($newValues)) {
1782
            $newValues = $bestFitExponential->getXValues();
1783
        }
1784
1785
        $returnArray = array();
1786
        foreach ($newValues as $xValue) {
1787
            $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
1788
        }
1789
1790
        return $returnArray;
1791
    }
1792
1793
1794
    /**
1795
     * HARMEAN
1796
     *
1797
     * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
1798
     *        arithmetic mean of reciprocals.
1799
     *
1800
     * Excel Function:
1801
     *        HARMEAN(value1[,value2[, ...]])
1802
     *
1803
     * @access    public
1804
     * @category Statistical Functions
1805
     * @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...
1806
     * @return    float
1807
     */
1808
    public static function HARMEAN()
1809
    {
1810
        // Return value
1811
        $returnValue = Functions::NA();
1812
1813
        // Loop through arguments
1814
        $aArgs = Functions::flattenArray(func_get_args());
1815
        if (self::MIN($aArgs) < 0) {
1816
            return Functions::NAN();
1817
        }
1818
        $aCount = 0;
1819
        foreach ($aArgs as $arg) {
1820
            // Is it a numeric value?
1821
            if ((is_numeric($arg)) && (!is_string($arg))) {
1822
                if ($arg <= 0) {
1823
                    return Functions::NAN();
1824
                }
1825
                if (is_null($returnValue)) {
1826
                    $returnValue = (1 / $arg);
1827
                } else {
1828
                    $returnValue += (1 / $arg);
1829
                }
1830
                ++$aCount;
1831
            }
1832
        }
1833
1834
        // Return
1835
        if ($aCount > 0) {
1836
            return 1 / ($returnValue / $aCount);
1837
        } else {
1838
            return $returnValue;
1839
        }
1840
    }
1841
1842
1843
    /**
1844
     * HYPGEOMDIST
1845
     *
1846
     * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of
1847
     * sample successes, given the sample size, population successes, and population size.
1848
     *
1849
     * @param    float        $sampleSuccesses        Number of successes in the sample
1850
     * @param    float        $sampleNumber            Size of the sample
1851
     * @param    float        $populationSuccesses    Number of successes in the population
1852
     * @param    float        $populationNumber        Population size
1853
     * @return    float
1854
     *
1855
     */
1856
    public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
1857
    {
1858
        $sampleSuccesses     = floor(Functions::flattenSingleValue($sampleSuccesses));
1859
        $sampleNumber        = floor(Functions::flattenSingleValue($sampleNumber));
1860
        $populationSuccesses = floor(Functions::flattenSingleValue($populationSuccesses));
1861
        $populationNumber    = floor(Functions::flattenSingleValue($populationNumber));
1862
1863
        if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
1864
            if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
1865
                return Functions::NAN();
1866
            }
1867
            if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) {
1868
                return Functions::NAN();
1869
            }
1870
            if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) {
1871
                return Functions::NAN();
1872
            }
1873
            return MathTrig::COMBIN($populationSuccesses, $sampleSuccesses) *
1874
                   MathTrig::COMBIN($populationNumber - $populationSuccesses, $sampleNumber - $sampleSuccesses) /
1875
                   MathTrig::COMBIN($populationNumber, $sampleNumber);
1876
        }
1877
        return Functions::VALUE();
1878
    }
1879
1880
1881
    /**
1882
     * INTERCEPT
1883
     *
1884
     * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
1885
     *
1886
     * @param    array of mixed        Data Series Y
1887
     * @param    array of mixed        Data Series X
1888
     * @return    float
1889
     */
1890 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...
1891
    {
1892
        if (!self::checkTrendArrays($yValues, $xValues)) {
1893
            return Functions::VALUE();
1894
        }
1895
        $yValueCount = count($yValues);
1896
        $xValueCount = count($xValues);
1897
1898
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
1899
            return Functions::NA();
1900
        } elseif ($yValueCount == 1) {
1901
            return Functions::DIV0();
1902
        }
1903
1904
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
1905
        return $bestFitLinear->getIntersect();
1906
    }
1907
1908
1909
    /**
1910
     * KURT
1911
     *
1912
     * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
1913
     * or flatness of a distribution compared with the normal distribution. Positive
1914
     * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
1915
     * relatively flat distribution.
1916
     *
1917
     * @param    array    Data Series
1918
     * @return    float
1919
     */
1920
    public static function KURT()
1921
    {
1922
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
1923
        $mean = self::AVERAGE($aArgs);
1924
        $stdDev = self::STDEV($aArgs);
1925
1926
        if ($stdDev > 0) {
1927
            $count = $summer = 0;
1928
            // Loop through arguments
1929 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...
1930
                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...
1931
                    (!Functions::isMatrixValue($k))) {
1932
                } else {
1933
                    // Is it a numeric value?
1934
                    if ((is_numeric($arg)) && (!is_string($arg))) {
1935
                        $summer += pow((($arg - $mean) / $stdDev), 4);
1936
                        ++$count;
1937
                    }
1938
                }
1939
            }
1940
1941
            // Return
1942
            if ($count > 3) {
1943
                return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1, 2) / (($count-2) * ($count-3)));
1944
            }
1945
        }
1946
        return Functions::DIV0();
1947
    }
1948
1949
1950
    /**
1951
     * LARGE
1952
     *
1953
     * Returns the nth largest value in a data set. You can use this function to
1954
     *        select a value based on its relative standing.
1955
     *
1956
     * Excel Function:
1957
     *        LARGE(value1[,value2[, ...]],entry)
1958
     *
1959
     * @access    public
1960
     * @category Statistical Functions
1961
     * @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...
1962
     * @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...
1963
     * @return    float
1964
     *
1965
     */
1966 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...
1967
    {
1968
        $aArgs = Functions::flattenArray(func_get_args());
1969
1970
        // Calculate
1971
        $entry = floor(array_pop($aArgs));
1972
1973
        if ((is_numeric($entry)) && (!is_string($entry))) {
1974
            $mArgs = array();
1975
            foreach ($aArgs as $arg) {
1976
                // Is it a numeric value?
1977
                if ((is_numeric($arg)) && (!is_string($arg))) {
1978
                    $mArgs[] = $arg;
1979
                }
1980
            }
1981
            $count = self::COUNT($mArgs);
1982
            $entry = floor(--$entry);
1983
            if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
1984
                return Functions::NAN();
1985
            }
1986
            rsort($mArgs);
1987
            return $mArgs[$entry];
1988
        }
1989
        return Functions::VALUE();
1990
    }
1991
1992
1993
    /**
1994
     * LINEST
1995
     *
1996
     * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
1997
     *        and then returns an array that describes the line.
1998
     *
1999
     * @param    array of mixed        Data Series Y
2000
     * @param    array of mixed        Data Series X
2001
     * @param    boolean                A logical value specifying whether to force the intersect to equal 0.
2002
     * @param    boolean                A logical value specifying whether to return additional regression statistics.
2003
     * @return    array
2004
     */
2005
    public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
2006
    {
2007
        $const = (is_null($const)) ? true : (boolean) Functions::flattenSingleValue($const);
2008
        $stats = (is_null($stats)) ? false : (boolean) Functions::flattenSingleValue($stats);
2009
        if (is_null($xValues)) {
2010
            $xValues = range(1, count(Functions::flattenArray($yValues)));
2011
        }
2012
2013
        if (!self::checkTrendArrays($yValues, $xValues)) {
2014
            return Functions::VALUE();
2015
        }
2016
        $yValueCount = count($yValues);
2017
        $xValueCount = count($xValues);
2018
2019
2020
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2021
            return Functions::NA();
2022
        } elseif ($yValueCount == 1) {
2023
            return 0;
2024
        }
2025
2026
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues, $const);
2027 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...
2028
            return array(
2029
                array(
2030
                    $bestFitLinear->getSlope(),
2031
                    $bestFitLinear->getSlopeSE(),
2032
                    $bestFitLinear->getGoodnessOfFit(),
2033
                    $bestFitLinear->getF(),
2034
                    $bestFitLinear->getSSRegression(),
2035
                ),
2036
                array(
2037
                    $bestFitLinear->getIntersect(),
2038
                    $bestFitLinear->getIntersectSE(),
2039
                    $bestFitLinear->getStdevOfResiduals(),
2040
                    $bestFitLinear->getDFResiduals(),
2041
                    $bestFitLinear->getSSResiduals()
2042
                )
2043
            );
2044
        } else {
2045
            return array(
2046
                $bestFitLinear->getSlope(),
2047
                $bestFitLinear->getIntersect()
2048
            );
2049
        }
2050
    }
2051
2052
2053
    /**
2054
     * LOGEST
2055
     *
2056
     * Calculates an exponential curve that best fits the X and Y data series,
2057
     *        and then returns an array that describes the line.
2058
     *
2059
     * @param    array of mixed        Data Series Y
2060
     * @param    array of mixed        Data Series X
2061
     * @param    boolean                A logical value specifying whether to force the intersect to equal 0.
2062
     * @param    boolean                A logical value specifying whether to return additional regression statistics.
2063
     * @return    array
2064
     */
2065
    public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false)
2066
    {
2067
        $const = (is_null($const)) ? true : (boolean) Functions::flattenSingleValue($const);
2068
        $stats = (is_null($stats)) ? false : (boolean) Functions::flattenSingleValue($stats);
2069
        if (is_null($xValues)) {
2070
            $xValues = range(1, count(Functions::flattenArray($yValues)));
2071
        }
2072
2073
        if (!self::checkTrendArrays($yValues, $xValues)) {
2074
            return Functions::VALUE();
2075
        }
2076
        $yValueCount = count($yValues);
2077
        $xValueCount = count($xValues);
2078
2079
        foreach ($yValues as $value) {
2080
            if ($value <= 0.0) {
2081
                return Functions::NAN();
2082
            }
2083
        }
2084
2085
2086
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2087
            return Functions::NA();
2088
        } elseif ($yValueCount == 1) {
2089
            return 1;
2090
        }
2091
2092
        $bestFitExponential = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_EXPONENTIAL, $yValues, $xValues, $const);
2093 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...
2094
            return array(
2095
                array(
2096
                    $bestFitExponential->getSlope(),
2097
                    $bestFitExponential->getSlopeSE(),
2098
                    $bestFitExponential->getGoodnessOfFit(),
2099
                    $bestFitExponential->getF(),
2100
                    $bestFitExponential->getSSRegression(),
2101
                ),
2102
                array(
2103
                    $bestFitExponential->getIntersect(),
2104
                    $bestFitExponential->getIntersectSE(),
2105
                    $bestFitExponential->getStdevOfResiduals(),
2106
                    $bestFitExponential->getDFResiduals(),
2107
                    $bestFitExponential->getSSResiduals()
2108
                )
2109
            );
2110
        } else {
2111
            return array(
2112
                $bestFitExponential->getSlope(),
2113
                $bestFitExponential->getIntersect()
2114
            );
2115
        }
2116
    }
2117
2118
2119
    /**
2120
     * LOGINV
2121
     *
2122
     * Returns the inverse of the normal cumulative distribution
2123
     *
2124
     * @param    float        $probability
2125
     * @param    float        $mean
2126
     * @param    float        $stdDev
2127
     * @return    float
2128
     *
2129
     * @todo    Try implementing P J Acklam's refinement algorithm for greater
2130
     *            accuracy if I can get my head round the mathematics
2131
     *            (as described at) http://home.online.no/~pjacklam/notes/invnorm/
2132
     */
2133 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...
2134
    {
2135
        $probability = Functions::flattenSingleValue($probability);
2136
        $mean        = Functions::flattenSingleValue($mean);
2137
        $stdDev      = Functions::flattenSingleValue($stdDev);
2138
2139
        if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2140
            if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) {
2141
                return Functions::NAN();
2142
            }
2143
            return exp($mean + $stdDev * self::NORMSINV($probability));
2144
        }
2145
        return Functions::VALUE();
2146
    }
2147
2148
2149
    /**
2150
     * LOGNORMDIST
2151
     *
2152
     * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed
2153
     * with parameters mean and standard_dev.
2154
     *
2155
     * @param    float        $value
2156
     * @param    float        $mean
2157
     * @param    float        $stdDev
2158
     * @return    float
2159
     */
2160
    public static function LOGNORMDIST($value, $mean, $stdDev)
2161
    {
2162
        $value  = Functions::flattenSingleValue($value);
2163
        $mean   = Functions::flattenSingleValue($mean);
2164
        $stdDev = Functions::flattenSingleValue($stdDev);
2165
2166
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2167
            if (($value <= 0) || ($stdDev <= 0)) {
2168
                return Functions::NAN();
2169
            }
2170
            return self::NORMSDIST((log($value) - $mean) / $stdDev);
2171
        }
2172
        return Functions::VALUE();
2173
    }
2174
2175
2176
    /**
2177
     * MAX
2178
     *
2179
     * MAX returns the value of the element of the values passed that has the highest value,
2180
     *        with negative numbers considered smaller than positive numbers.
2181
     *
2182
     * Excel Function:
2183
     *        MAX(value1[,value2[, ...]])
2184
     *
2185
     * @access    public
2186
     * @category Statistical Functions
2187
     * @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...
2188
     * @return    float
2189
     */
2190 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...
2191
    {
2192
        $returnValue = null;
2193
2194
        // Loop through arguments
2195
        $aArgs = Functions::flattenArray(func_get_args());
2196
        foreach ($aArgs as $arg) {
2197
            // Is it a numeric value?
2198
            if ((is_numeric($arg)) && (!is_string($arg))) {
2199
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2200
                    $returnValue = $arg;
2201
                }
2202
            }
2203
        }
2204
2205
        if (is_null($returnValue)) {
2206
            return 0;
2207
        }
2208
        return $returnValue;
2209
    }
2210
2211
2212
    /**
2213
     * MAXA
2214
     *
2215
     * Returns the greatest value in a list of arguments, including numbers, text, and logical values
2216
     *
2217
     * Excel Function:
2218
     *        MAXA(value1[,value2[, ...]])
2219
     *
2220
     * @access    public
2221
     * @category Statistical Functions
2222
     * @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...
2223
     * @return    float
2224
     */
2225 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...
2226
    {
2227
        $returnValue = null;
2228
2229
        // Loop through arguments
2230
        $aArgs = Functions::flattenArray(func_get_args());
2231
        foreach ($aArgs as $arg) {
2232
            // Is it a numeric value?
2233
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2234
                if (is_bool($arg)) {
2235
                    $arg = (integer) $arg;
2236
                } elseif (is_string($arg)) {
2237
                    $arg = 0;
2238
                }
2239
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2240
                    $returnValue = $arg;
2241
                }
2242
            }
2243
        }
2244
2245
        if (is_null($returnValue)) {
2246
            return 0;
2247
        }
2248
        return $returnValue;
2249
    }
2250
2251
2252
    /**
2253
     * MAXIF
2254
     *
2255
     * Counts the maximum value within a range of cells that contain numbers within the list of arguments
2256
     *
2257
     * Excel Function:
2258
     *        MAXIF(value1[,value2[, ...]],condition)
2259
     *
2260
     * @access    public
2261
     * @category Mathematical and Trigonometric Functions
2262
     * @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...
2263
     * @param    string        $condition        The criteria that defines which cells will be checked.
2264
     * @return    float
2265
     */
2266 View Code Duplication
    public static function MAXIF($aArgs, $condition, $sumArgs = array())
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...
2267
    {
2268
        $returnValue = null;
2269
2270
        $aArgs = Functions::flattenArray($aArgs);
2271
        $sumArgs = Functions::flattenArray($sumArgs);
2272
        if (empty($sumArgs)) {
2273
            $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...
2274
        }
2275
        $condition = Functions::ifCondition($condition);
2276
        // Loop through arguments
2277
        foreach ($aArgs as $key => $arg) {
2278
            if (!is_numeric($arg)) {
2279
                $arg = \PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
2280
            }
2281
            $testCondition = '='.$arg.$condition;
2282
            if (\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2283
                if ((is_null($returnValue)) || ($arg > $returnValue)) {
2284
                    $returnValue = $arg;
2285
                }
2286
            }
2287
        }
2288
2289
        return $returnValue;
2290
    }
2291
2292
    /**
2293
     * MEDIAN
2294
     *
2295
     * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
2296
     *
2297
     * Excel Function:
2298
     *        MEDIAN(value1[,value2[, ...]])
2299
     *
2300
     * @access    public
2301
     * @category Statistical Functions
2302
     * @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...
2303
     * @return    float
2304
     */
2305
    public static function MEDIAN()
2306
    {
2307
        $returnValue = Functions::NAN();
2308
2309
        $mArgs = array();
2310
        // Loop through arguments
2311
        $aArgs = Functions::flattenArray(func_get_args());
2312
        foreach ($aArgs as $arg) {
2313
            // Is it a numeric value?
2314
            if ((is_numeric($arg)) && (!is_string($arg))) {
2315
                $mArgs[] = $arg;
2316
            }
2317
        }
2318
2319
        $mValueCount = count($mArgs);
2320
        if ($mValueCount > 0) {
2321
            sort($mArgs, SORT_NUMERIC);
2322
            $mValueCount = $mValueCount / 2;
2323
            if ($mValueCount == floor($mValueCount)) {
2324
                $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
2325
            } else {
2326
                $mValueCount = floor($mValueCount);
2327
                $returnValue = $mArgs[$mValueCount];
2328
            }
2329
        }
2330
2331
        return $returnValue;
2332
    }
2333
2334
2335
    /**
2336
     * MIN
2337
     *
2338
     * MIN returns the value of the element of the values passed that has the smallest value,
2339
     *        with negative numbers considered smaller than positive numbers.
2340
     *
2341
     * Excel Function:
2342
     *        MIN(value1[,value2[, ...]])
2343
     *
2344
     * @access    public
2345
     * @category Statistical Functions
2346
     * @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...
2347
     * @return    float
2348
     */
2349 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...
2350
    {
2351
        $returnValue = null;
2352
2353
        // Loop through arguments
2354
        $aArgs = Functions::flattenArray(func_get_args());
2355
        foreach ($aArgs as $arg) {
2356
            // Is it a numeric value?
2357
            if ((is_numeric($arg)) && (!is_string($arg))) {
2358
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2359
                    $returnValue = $arg;
2360
                }
2361
            }
2362
        }
2363
2364
        if (is_null($returnValue)) {
2365
            return 0;
2366
        }
2367
        return $returnValue;
2368
    }
2369
2370
2371
    /**
2372
     * MINA
2373
     *
2374
     * Returns the smallest value in a list of arguments, including numbers, text, and logical values
2375
     *
2376
     * Excel Function:
2377
     *        MINA(value1[,value2[, ...]])
2378
     *
2379
     * @access    public
2380
     * @category Statistical Functions
2381
     * @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...
2382
     * @return    float
2383
     */
2384 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...
2385
    {
2386
        $returnValue = null;
2387
2388
        // Loop through arguments
2389
        $aArgs = Functions::flattenArray(func_get_args());
2390
        foreach ($aArgs as $arg) {
2391
            // Is it a numeric value?
2392
            if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
2393
                if (is_bool($arg)) {
2394
                    $arg = (integer) $arg;
2395
                } elseif (is_string($arg)) {
2396
                    $arg = 0;
2397
                }
2398
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2399
                    $returnValue = $arg;
2400
                }
2401
            }
2402
        }
2403
2404
        if (is_null($returnValue)) {
2405
            return 0;
2406
        }
2407
        return $returnValue;
2408
    }
2409
2410
2411
    /**
2412
     * MINIF
2413
     *
2414
     * Returns the minimum value within a range of cells that contain numbers within the list of arguments
2415
     *
2416
     * Excel Function:
2417
     *        MINIF(value1[,value2[, ...]],condition)
2418
     *
2419
     * @access    public
2420
     * @category Mathematical and Trigonometric Functions
2421
     * @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...
2422
     * @param    string        $condition        The criteria that defines which cells will be checked.
2423
     * @return    float
2424
     */
2425 View Code Duplication
    public static function MINIF($aArgs, $condition, $sumArgs = array())
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...
2426
    {
2427
        $returnValue = null;
2428
2429
        $aArgs = Functions::flattenArray($aArgs);
2430
        $sumArgs = Functions::flattenArray($sumArgs);
2431
        if (empty($sumArgs)) {
2432
            $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...
2433
        }
2434
        $condition = Functions::ifCondition($condition);
2435
        // Loop through arguments
2436
        foreach ($aArgs as $key => $arg) {
2437
            if (!is_numeric($arg)) {
2438
                $arg = \PhpSpreadsheet\Calculation::wrapResult(strtoupper($arg));
2439
            }
2440
            $testCondition = '='.$arg.$condition;
2441
            if (\PhpSpreadsheet\Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
2442
                if ((is_null($returnValue)) || ($arg < $returnValue)) {
2443
                    $returnValue = $arg;
2444
                }
2445
            }
2446
        }
2447
2448
        return $returnValue;
2449
    }
2450
2451
2452
    //
2453
    //    Special variant of array_count_values that isn't limited to strings and integers,
2454
    //        but can work with floating point numbers as values
2455
    //
2456
    private static function modeCalc($data)
2457
    {
2458
        $frequencyArray = array();
2459
        foreach ($data as $datum) {
2460
            $found = false;
2461
            foreach ($frequencyArray as $key => $value) {
2462
                if ((string) $value['value'] == (string) $datum) {
2463
                    ++$frequencyArray[$key]['frequency'];
2464
                    $found = true;
2465
                    break;
2466
                }
2467
            }
2468
            if (!$found) {
2469
                $frequencyArray[] = array(
2470
                    'value'     => $datum,
2471
                    'frequency' => 1
2472
                );
2473
            }
2474
        }
2475
2476
        foreach ($frequencyArray as $key => $value) {
2477
            $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...
2478
            $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...
2479
        }
2480
        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...
2481
2482
        if ($frequencyArray[0]['frequency'] == 1) {
2483
            return Functions::NA();
2484
        }
2485
        return $frequencyArray[0]['value'];
2486
    }
2487
2488
2489
    /**
2490
     * MODE
2491
     *
2492
     * Returns the most frequently occurring, or repetitive, value in an array or range of data
2493
     *
2494
     * Excel Function:
2495
     *        MODE(value1[,value2[, ...]])
2496
     *
2497
     * @access    public
2498
     * @category Statistical Functions
2499
     * @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...
2500
     * @return    float
2501
     */
2502
    public static function MODE()
2503
    {
2504
        $returnValue = Functions::NA();
2505
2506
        // Loop through arguments
2507
        $aArgs = Functions::flattenArray(func_get_args());
2508
2509
        $mArgs = array();
2510
        foreach ($aArgs as $arg) {
2511
            // Is it a numeric value?
2512
            if ((is_numeric($arg)) && (!is_string($arg))) {
2513
                $mArgs[] = $arg;
2514
            }
2515
        }
2516
2517
        if (!empty($mArgs)) {
2518
            return self::modeCalc($mArgs);
2519
        }
2520
2521
        return $returnValue;
2522
    }
2523
2524
2525
    /**
2526
     * NEGBINOMDIST
2527
     *
2528
     * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
2529
     *        there will be number_f failures before the number_s-th success, when the constant
2530
     *        probability of a success is probability_s. This function is similar to the binomial
2531
     *        distribution, except that the number of successes is fixed, and the number of trials is
2532
     *        variable. Like the binomial, trials are assumed to be independent.
2533
     *
2534
     * @param    float        $failures        Number of Failures
2535
     * @param    float        $successes        Threshold number of Successes
2536
     * @param    float        $probability    Probability of success on each trial
2537
     * @return    float
2538
     *
2539
     */
2540
    public static function NEGBINOMDIST($failures, $successes, $probability)
2541
    {
2542
        $failures    = floor(Functions::flattenSingleValue($failures));
2543
        $successes   = floor(Functions::flattenSingleValue($successes));
2544
        $probability = Functions::flattenSingleValue($probability);
2545
2546
        if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) {
2547
            if (($failures < 0) || ($successes < 1)) {
2548
                return Functions::NAN();
2549
            } elseif (($probability < 0) || ($probability > 1)) {
2550
                return Functions::NAN();
2551
            }
2552
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
2553
                if (($failures + $successes - 1) <= 0) {
2554
                    return Functions::NAN();
2555
                }
2556
            }
2557
            return (MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures));
2558
        }
2559
        return Functions::VALUE();
2560
    }
2561
2562
2563
    /**
2564
     * NORMDIST
2565
     *
2566
     * Returns the normal distribution for the specified mean and standard deviation. This
2567
     * function has a very wide range of applications in statistics, including hypothesis
2568
     * testing.
2569
     *
2570
     * @param    float        $value
2571
     * @param    float        $mean        Mean Value
2572
     * @param    float        $stdDev        Standard Deviation
2573
     * @param    boolean        $cumulative
2574
     * @return    float
2575
     *
2576
     */
2577
    public static function NORMDIST($value, $mean, $stdDev, $cumulative)
2578
    {
2579
        $value  = Functions::flattenSingleValue($value);
2580
        $mean   = Functions::flattenSingleValue($mean);
2581
        $stdDev = Functions::flattenSingleValue($stdDev);
2582
2583
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2584
            if ($stdDev < 0) {
2585
                return Functions::NAN();
2586
            }
2587
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2588
                if ($cumulative) {
2589
                    return 0.5 * (1 + Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2))));
2590
                } else {
2591
                    return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev))));
2592
                }
2593
            }
2594
        }
2595
        return Functions::VALUE();
2596
    }
2597
2598
2599
    /**
2600
     * NORMINV
2601
     *
2602
     * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
2603
     *
2604
     * @param    float        $value
0 ignored issues
show
Bug introduced by
There is no parameter named $value. 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...
2605
     * @param    float        $mean        Mean Value
2606
     * @param    float        $stdDev        Standard Deviation
2607
     * @return    float
2608
     *
2609
     */
2610 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...
2611
    {
2612
        $probability = Functions::flattenSingleValue($probability);
2613
        $mean        = Functions::flattenSingleValue($mean);
2614
        $stdDev      = Functions::flattenSingleValue($stdDev);
2615
2616
        if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
2617
            if (($probability < 0) || ($probability > 1)) {
2618
                return Functions::NAN();
2619
            }
2620
            if ($stdDev < 0) {
2621
                return Functions::NAN();
2622
            }
2623
            return (self::inverseNcdf($probability) * $stdDev) + $mean;
2624
        }
2625
        return Functions::VALUE();
2626
    }
2627
2628
2629
    /**
2630
     * NORMSDIST
2631
     *
2632
     * Returns the standard normal cumulative distribution function. The distribution has
2633
     * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
2634
     * table of standard normal curve areas.
2635
     *
2636
     * @param    float        $value
2637
     * @return    float
2638
     */
2639
    public static function NORMSDIST($value)
2640
    {
2641
        $value = Functions::flattenSingleValue($value);
2642
2643
        return self::NORMDIST($value, 0, 1, true);
2644
    }
2645
2646
2647
    /**
2648
     * NORMSINV
2649
     *
2650
     * Returns the inverse of the standard normal cumulative distribution
2651
     *
2652
     * @param    float        $value
2653
     * @return    float
2654
     */
2655
    public static function NORMSINV($value)
2656
    {
2657
        return self::NORMINV($value, 0, 1);
2658
    }
2659
2660
2661
    /**
2662
     * PERCENTILE
2663
     *
2664
     * Returns the nth percentile of values in a range..
2665
     *
2666
     * Excel Function:
2667
     *        PERCENTILE(value1[,value2[, ...]],entry)
2668
     *
2669
     * @access    public
2670
     * @category Statistical Functions
2671
     * @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...
2672
     * @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...
2673
     * @return    float
2674
     */
2675
    public static function PERCENTILE()
2676
    {
2677
        $aArgs = Functions::flattenArray(func_get_args());
2678
2679
        // Calculate
2680
        $entry = array_pop($aArgs);
2681
2682
        if ((is_numeric($entry)) && (!is_string($entry))) {
2683
            if (($entry < 0) || ($entry > 1)) {
2684
                return Functions::NAN();
2685
            }
2686
            $mArgs = array();
2687
            foreach ($aArgs as $arg) {
2688
                // Is it a numeric value?
2689
                if ((is_numeric($arg)) && (!is_string($arg))) {
2690
                    $mArgs[] = $arg;
2691
                }
2692
            }
2693
            $mValueCount = count($mArgs);
2694
            if ($mValueCount > 0) {
2695
                sort($mArgs);
2696
                $count = self::COUNT($mArgs);
2697
                $index = $entry * ($count-1);
2698
                $iBase = floor($index);
2699
                if ($index == $iBase) {
2700
                    return $mArgs[$index];
2701
                } else {
2702
                    $iNext = $iBase + 1;
2703
                    $iProportion = $index - $iBase;
2704
                    return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
2705
                }
2706
            }
2707
        }
2708
        return Functions::VALUE();
2709
    }
2710
2711
2712
    /**
2713
     * PERCENTRANK
2714
     *
2715
     * Returns the rank of a value in a data set as a percentage of the data set.
2716
     *
2717
     * @param    array of number        An array of, or a reference to, a list of numbers.
2718
     * @param    number                The number whose rank you want to find.
2719
     * @param    number                The number of significant digits for the returned percentage value.
2720
     * @return    float
2721
     */
2722
    public static function PERCENTRANK($valueSet, $value, $significance = 3)
2723
    {
2724
        $valueSet     = Functions::flattenArray($valueSet);
2725
        $value        = Functions::flattenSingleValue($value);
2726
        $significance = (is_null($significance)) ? 3 : (integer) Functions::flattenSingleValue($significance);
2727
2728
        foreach ($valueSet as $key => $valueEntry) {
2729
            if (!is_numeric($valueEntry)) {
2730
                unset($valueSet[$key]);
2731
            }
2732
        }
2733
        sort($valueSet, SORT_NUMERIC);
2734
        $valueCount = count($valueSet);
2735
        if ($valueCount == 0) {
2736
            return Functions::NAN();
2737
        }
2738
2739
        $valueAdjustor = $valueCount - 1;
2740
        if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
2741
            return Functions::NA();
2742
        }
2743
2744
        $pos = array_search($value, $valueSet);
2745
        if ($pos === false) {
2746
            $pos = 0;
2747
            $testValue = $valueSet[0];
2748
            while ($testValue < $value) {
2749
                $testValue = $valueSet[++$pos];
2750
            }
2751
            --$pos;
2752
            $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
2753
        }
2754
2755
        return round($pos / $valueAdjustor, $significance);
2756
    }
2757
2758
2759
    /**
2760
     * PERMUT
2761
     *
2762
     * Returns the number of permutations for a given number of objects that can be
2763
     *        selected from number objects. A permutation is any set or subset of objects or
2764
     *        events where internal order is significant. Permutations are different from
2765
     *        combinations, for which the internal order is not significant. Use this function
2766
     *        for lottery-style probability calculations.
2767
     *
2768
     * @param    int        $numObjs    Number of different objects
2769
     * @param    int        $numInSet    Number of objects in each permutation
2770
     * @return    int        Number of permutations
2771
     */
2772 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...
2773
    {
2774
        $numObjs  = Functions::flattenSingleValue($numObjs);
2775
        $numInSet = Functions::flattenSingleValue($numInSet);
2776
2777
        if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
2778
            $numInSet = floor($numInSet);
2779
            if ($numObjs < $numInSet) {
2780
                return Functions::NAN();
2781
            }
2782
            return round(MathTrig::FACT($numObjs) / MathTrig::FACT($numObjs - $numInSet));
2783
        }
2784
        return Functions::VALUE();
2785
    }
2786
2787
2788
    /**
2789
     * POISSON
2790
     *
2791
     * Returns the Poisson distribution. A common application of the Poisson distribution
2792
     * is predicting the number of events over a specific time, such as the number of
2793
     * cars arriving at a toll plaza in 1 minute.
2794
     *
2795
     * @param    float        $value
2796
     * @param    float        $mean        Mean Value
2797
     * @param    boolean        $cumulative
2798
     * @return    float
2799
     *
2800
     */
2801
    public static function POISSON($value, $mean, $cumulative)
2802
    {
2803
        $value = Functions::flattenSingleValue($value);
2804
        $mean  = Functions::flattenSingleValue($mean);
2805
2806
        if ((is_numeric($value)) && (is_numeric($mean))) {
2807
            if (($value < 0) || ($mean <= 0)) {
2808
                return Functions::NAN();
2809
            }
2810
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
2811
                if ($cumulative) {
2812
                    $summer = 0;
2813
                    for ($i = 0; $i <= floor($value); ++$i) {
2814
                        $summer += pow($mean, $i) / MathTrig::FACT($i);
2815
                    }
2816
                    return exp(0-$mean) * $summer;
2817
                } else {
2818
                    return (exp(0-$mean) * pow($mean, $value)) / MathTrig::FACT($value);
2819
                }
2820
            }
2821
        }
2822
        return Functions::VALUE();
2823
    }
2824
2825
2826
    /**
2827
     * QUARTILE
2828
     *
2829
     * Returns the quartile of a data set.
2830
     *
2831
     * Excel Function:
2832
     *        QUARTILE(value1[,value2[, ...]],entry)
2833
     *
2834
     * @access    public
2835
     * @category Statistical Functions
2836
     * @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...
2837
     * @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...
2838
     * @return    float
2839
     */
2840
    public static function QUARTILE()
2841
    {
2842
        $aArgs = Functions::flattenArray(func_get_args());
2843
2844
        // Calculate
2845
        $entry = floor(array_pop($aArgs));
2846
2847
        if ((is_numeric($entry)) && (!is_string($entry))) {
2848
            $entry /= 4;
2849
            if (($entry < 0) || ($entry > 1)) {
2850
                return Functions::NAN();
2851
            }
2852
            return self::PERCENTILE($aArgs, $entry);
2853
        }
2854
        return Functions::VALUE();
2855
    }
2856
2857
2858
    /**
2859
     * RANK
2860
     *
2861
     * Returns the rank of a number in a list of numbers.
2862
     *
2863
     * @param    number                The number whose rank you want to find.
2864
     * @param    array of number        An array of, or a reference to, a list of numbers.
2865
     * @param    mixed                Order to sort the values in the value set
2866
     * @return    float
2867
     */
2868
    public static function RANK($value, $valueSet, $order = 0)
2869
    {
2870
        $value = Functions::flattenSingleValue($value);
2871
        $valueSet = Functions::flattenArray($valueSet);
2872
        $order = (is_null($order)) ? 0 : (integer) Functions::flattenSingleValue($order);
2873
2874
        foreach ($valueSet as $key => $valueEntry) {
2875
            if (!is_numeric($valueEntry)) {
2876
                unset($valueSet[$key]);
2877
            }
2878
        }
2879
2880
        if ($order == 0) {
2881
            rsort($valueSet, SORT_NUMERIC);
2882
        } else {
2883
            sort($valueSet, SORT_NUMERIC);
2884
        }
2885
        $pos = array_search($value, $valueSet);
2886
        if ($pos === false) {
2887
            return Functions::NA();
2888
        }
2889
2890
        return ++$pos;
2891
    }
2892
2893
2894
    /**
2895
     * RSQ
2896
     *
2897
     * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
2898
     *
2899
     * @param    array of mixed        Data Series Y
2900
     * @param    array of mixed        Data Series X
2901
     * @return    float
2902
     */
2903 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...
2904
    {
2905
        if (!self::checkTrendArrays($yValues, $xValues)) {
2906
            return Functions::VALUE();
2907
        }
2908
        $yValueCount = count($yValues);
2909
        $xValueCount = count($xValues);
2910
2911
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2912
            return Functions::NA();
2913
        } elseif ($yValueCount == 1) {
2914
            return Functions::DIV0();
2915
        }
2916
2917
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
2918
        return $bestFitLinear->getGoodnessOfFit();
2919
    }
2920
2921
2922
    /**
2923
     * SKEW
2924
     *
2925
     * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
2926
     * of a distribution around its mean. Positive skewness indicates a distribution with an
2927
     * asymmetric tail extending toward more positive values. Negative skewness indicates a
2928
     * distribution with an asymmetric tail extending toward more negative values.
2929
     *
2930
     * @param    array    Data Series
2931
     * @return    float
2932
     */
2933
    public static function SKEW()
2934
    {
2935
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
2936
        $mean = self::AVERAGE($aArgs);
2937
        $stdDev = self::STDEV($aArgs);
2938
2939
        $count = $summer = 0;
2940
        // Loop through arguments
2941 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...
2942
            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...
2943
                (!Functions::isMatrixValue($k))) {
2944
            } else {
2945
                // Is it a numeric value?
2946
                if ((is_numeric($arg)) && (!is_string($arg))) {
2947
                    $summer += pow((($arg - $mean) / $stdDev), 3);
2948
                    ++$count;
2949
                }
2950
            }
2951
        }
2952
2953
        if ($count > 2) {
2954
            return $summer * ($count / (($count-1) * ($count-2)));
2955
        }
2956
        return Functions::DIV0();
2957
    }
2958
2959
2960
    /**
2961
     * SLOPE
2962
     *
2963
     * Returns the slope of the linear regression line through data points in known_y's and known_x's.
2964
     *
2965
     * @param    array of mixed        Data Series Y
2966
     * @param    array of mixed        Data Series X
2967
     * @return    float
2968
     */
2969 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...
2970
    {
2971
        if (!self::checkTrendArrays($yValues, $xValues)) {
2972
            return Functions::VALUE();
2973
        }
2974
        $yValueCount = count($yValues);
2975
        $xValueCount = count($xValues);
2976
2977
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
2978
            return Functions::NA();
2979
        } elseif ($yValueCount == 1) {
2980
            return Functions::DIV0();
2981
        }
2982
2983
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
2984
        return $bestFitLinear->getSlope();
2985
    }
2986
2987
2988
    /**
2989
     * SMALL
2990
     *
2991
     * Returns the nth smallest value in a data set. You can use this function to
2992
     *        select a value based on its relative standing.
2993
     *
2994
     * Excel Function:
2995
     *        SMALL(value1[,value2[, ...]],entry)
2996
     *
2997
     * @access    public
2998
     * @category Statistical Functions
2999
     * @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...
3000
     * @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...
3001
     * @return    float
3002
     */
3003 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...
3004
    {
3005
        $aArgs = Functions::flattenArray(func_get_args());
3006
3007
        // Calculate
3008
        $entry = array_pop($aArgs);
3009
3010
        if ((is_numeric($entry)) && (!is_string($entry))) {
3011
            $mArgs = array();
3012
            foreach ($aArgs as $arg) {
3013
                // Is it a numeric value?
3014
                if ((is_numeric($arg)) && (!is_string($arg))) {
3015
                    $mArgs[] = $arg;
3016
                }
3017
            }
3018
            $count = self::COUNT($mArgs);
3019
            $entry = floor(--$entry);
3020
            if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
3021
                return Functions::NAN();
3022
            }
3023
            sort($mArgs);
3024
            return $mArgs[$entry];
3025
        }
3026
        return Functions::VALUE();
3027
    }
3028
3029
3030
    /**
3031
     * STANDARDIZE
3032
     *
3033
     * Returns a normalized value from a distribution characterized by mean and standard_dev.
3034
     *
3035
     * @param    float    $value        Value to normalize
3036
     * @param    float    $mean        Mean Value
3037
     * @param    float    $stdDev        Standard Deviation
3038
     * @return    float    Standardized value
3039
     */
3040 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...
3041
    {
3042
        $value  = Functions::flattenSingleValue($value);
3043
        $mean   = Functions::flattenSingleValue($mean);
3044
        $stdDev = Functions::flattenSingleValue($stdDev);
3045
3046
        if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
3047
            if ($stdDev <= 0) {
3048
                return Functions::NAN();
3049
            }
3050
            return ($value - $mean) / $stdDev ;
3051
        }
3052
        return Functions::VALUE();
3053
    }
3054
3055
3056
    /**
3057
     * STDEV
3058
     *
3059
     * Estimates standard deviation based on a sample. The standard deviation is a measure of how
3060
     *        widely values are dispersed from the average value (the mean).
3061
     *
3062
     * Excel Function:
3063
     *        STDEV(value1[,value2[, ...]])
3064
     *
3065
     * @access    public
3066
     * @category Statistical Functions
3067
     * @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...
3068
     * @return    float
3069
     */
3070 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...
3071
    {
3072
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3073
3074
        // Return value
3075
        $returnValue = null;
3076
3077
        $aMean = self::AVERAGE($aArgs);
3078
        if (!is_null($aMean)) {
3079
            $aCount = -1;
3080
            foreach ($aArgs as $k => $arg) {
3081
                if ((is_bool($arg)) &&
3082
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
3083
                    $arg = (integer) $arg;
3084
                }
3085
                // Is it a numeric value?
3086
                if ((is_numeric($arg)) && (!is_string($arg))) {
3087
                    if (is_null($returnValue)) {
3088
                        $returnValue = pow(($arg - $aMean), 2);
3089
                    } else {
3090
                        $returnValue += pow(($arg - $aMean), 2);
3091
                    }
3092
                    ++$aCount;
3093
                }
3094
            }
3095
3096
            // Return
3097
            if (($aCount > 0) && ($returnValue >= 0)) {
3098
                return sqrt($returnValue / $aCount);
3099
            }
3100
        }
3101
        return Functions::DIV0();
3102
    }
3103
3104
3105
    /**
3106
     * STDEVA
3107
     *
3108
     * Estimates standard deviation based on a sample, including numbers, text, and logical values
3109
     *
3110
     * Excel Function:
3111
     *        STDEVA(value1[,value2[, ...]])
3112
     *
3113
     * @access    public
3114
     * @category Statistical Functions
3115
     * @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...
3116
     * @return    float
3117
     */
3118 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...
3119
    {
3120
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3121
3122
        $returnValue = null;
3123
3124
        $aMean = self::AVERAGEA($aArgs);
3125
        if (!is_null($aMean)) {
3126
            $aCount = -1;
3127
            foreach ($aArgs as $k => $arg) {
3128
                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...
3129
                    (!Functions::isMatrixValue($k))) {
3130
                } else {
3131
                    // Is it a numeric value?
3132
                    if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3133
                        if (is_bool($arg)) {
3134
                            $arg = (integer) $arg;
3135
                        } elseif (is_string($arg)) {
3136
                            $arg = 0;
3137
                        }
3138
                        if (is_null($returnValue)) {
3139
                            $returnValue = pow(($arg - $aMean), 2);
3140
                        } else {
3141
                            $returnValue += pow(($arg - $aMean), 2);
3142
                        }
3143
                        ++$aCount;
3144
                    }
3145
                }
3146
            }
3147
3148
            if (($aCount > 0) && ($returnValue >= 0)) {
3149
                return sqrt($returnValue / $aCount);
3150
            }
3151
        }
3152
        return Functions::DIV0();
3153
    }
3154
3155
3156
    /**
3157
     * STDEVP
3158
     *
3159
     * Calculates standard deviation based on the entire population
3160
     *
3161
     * Excel Function:
3162
     *        STDEVP(value1[,value2[, ...]])
3163
     *
3164
     * @access    public
3165
     * @category Statistical Functions
3166
     * @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...
3167
     * @return    float
3168
     */
3169 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...
3170
    {
3171
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3172
3173
        $returnValue = null;
3174
3175
        $aMean = self::AVERAGE($aArgs);
3176
        if (!is_null($aMean)) {
3177
            $aCount = 0;
3178
            foreach ($aArgs as $k => $arg) {
3179
                if ((is_bool($arg)) &&
3180
                    ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) {
3181
                    $arg = (integer) $arg;
3182
                }
3183
                // Is it a numeric value?
3184
                if ((is_numeric($arg)) && (!is_string($arg))) {
3185
                    if (is_null($returnValue)) {
3186
                        $returnValue = pow(($arg - $aMean), 2);
3187
                    } else {
3188
                        $returnValue += pow(($arg - $aMean), 2);
3189
                    }
3190
                    ++$aCount;
3191
                }
3192
            }
3193
3194
            if (($aCount > 0) && ($returnValue >= 0)) {
3195
                return sqrt($returnValue / $aCount);
3196
            }
3197
        }
3198
        return Functions::DIV0();
3199
    }
3200
3201
3202
    /**
3203
     * STDEVPA
3204
     *
3205
     * Calculates standard deviation based on the entire population, including numbers, text, and logical values
3206
     *
3207
     * Excel Function:
3208
     *        STDEVPA(value1[,value2[, ...]])
3209
     *
3210
     * @access    public
3211
     * @category Statistical Functions
3212
     * @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...
3213
     * @return    float
3214
     */
3215 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...
3216
    {
3217
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3218
3219
        $returnValue = null;
3220
3221
        $aMean = self::AVERAGEA($aArgs);
3222
        if (!is_null($aMean)) {
3223
            $aCount = 0;
3224
            foreach ($aArgs as $k => $arg) {
3225
                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...
3226
                    (!Functions::isMatrixValue($k))) {
3227
                } else {
3228
                    // Is it a numeric value?
3229
                    if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3230
                        if (is_bool($arg)) {
3231
                            $arg = (integer) $arg;
3232
                        } elseif (is_string($arg)) {
3233
                            $arg = 0;
3234
                        }
3235
                        if (is_null($returnValue)) {
3236
                            $returnValue = pow(($arg - $aMean), 2);
3237
                        } else {
3238
                            $returnValue += pow(($arg - $aMean), 2);
3239
                        }
3240
                        ++$aCount;
3241
                    }
3242
                }
3243
            }
3244
3245
            if (($aCount > 0) && ($returnValue >= 0)) {
3246
                return sqrt($returnValue / $aCount);
3247
            }
3248
        }
3249
        return Functions::DIV0();
3250
    }
3251
3252
3253
    /**
3254
     * STEYX
3255
     *
3256
     * Returns the standard error of the predicted y-value for each x in the regression.
3257
     *
3258
     * @param    array of mixed        Data Series Y
3259
     * @param    array of mixed        Data Series X
3260
     * @return    float
3261
     */
3262 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...
3263
    {
3264
        if (!self::checkTrendArrays($yValues, $xValues)) {
3265
            return Functions::VALUE();
3266
        }
3267
        $yValueCount = count($yValues);
3268
        $xValueCount = count($xValues);
3269
3270
        if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
3271
            return Functions::NA();
3272
        } elseif ($yValueCount == 1) {
3273
            return Functions::DIV0();
3274
        }
3275
3276
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues);
3277
        return $bestFitLinear->getStdevOfResiduals();
3278
    }
3279
3280
3281
    /**
3282
     * TDIST
3283
     *
3284
     * Returns the probability of Student's T distribution.
3285
     *
3286
     * @param    float        $value            Value for the function
3287
     * @param    float        $degrees        degrees of freedom
3288
     * @param    float        $tails            number of tails (1 or 2)
3289
     * @return    float
3290
     */
3291
    public static function TDIST($value, $degrees, $tails)
3292
    {
3293
        $value        = Functions::flattenSingleValue($value);
3294
        $degrees    = floor(Functions::flattenSingleValue($degrees));
3295
        $tails        = floor(Functions::flattenSingleValue($tails));
3296
3297
        if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) {
3298
            if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
3299
                return Functions::NAN();
3300
            }
3301
            //    tdist, which finds the probability that corresponds to a given value
3302
            //    of t with k degrees of freedom. This algorithm is translated from a
3303
            //    pascal function on p81 of "Statistical Computing in Pascal" by D
3304
            //    Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
3305
            //    London). The above Pascal algorithm is itself a translation of the
3306
            //    fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
3307
            //    Laboratory as reported in (among other places) "Applied Statistics
3308
            //    Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
3309
            //    Horwood Ltd.; W. Sussex, England).
3310
            $tterm = $degrees;
3311
            $ttheta = atan2($value, sqrt($tterm));
3312
            $tc = cos($ttheta);
3313
            $ts = sin($ttheta);
3314
            $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...
3315
3316
            if (($degrees % 2) == 1) {
3317
                $ti = 3;
3318
                $tterm = $tc;
3319
            } else {
3320
                $ti = 2;
3321
                $tterm = 1;
3322
            }
3323
3324
            $tsum = $tterm;
3325
            while ($ti < $degrees) {
3326
                $tterm *= $tc * $tc * ($ti - 1) / $ti;
3327
                $tsum += $tterm;
3328
                $ti += 2;
3329
            }
3330
            $tsum *= $ts;
3331
            if (($degrees % 2) == 1) {
3332
                $tsum = M_2DIVPI * ($tsum + $ttheta);
3333
            }
3334
            $tValue = 0.5 * (1 + $tsum);
3335
            if ($tails == 1) {
3336
                return 1 - abs($tValue);
3337
            } else {
3338
                return 1 - abs((1 - $tValue) - $tValue);
3339
            }
3340
        }
3341
        return Functions::VALUE();
3342
    }
3343
3344
3345
    /**
3346
     * TINV
3347
     *
3348
     * Returns the one-tailed probability of the chi-squared distribution.
3349
     *
3350
     * @param    float        $probability    Probability for the function
3351
     * @param    float        $degrees        degrees of freedom
3352
     * @return    float
3353
     */
3354 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...
3355
    {
3356
        $probability = Functions::flattenSingleValue($probability);
3357
        $degrees     = floor(Functions::flattenSingleValue($degrees));
3358
3359
        if ((is_numeric($probability)) && (is_numeric($degrees))) {
3360
            $xLo = 100;
3361
            $xHi = 0;
3362
3363
            $x = $xNew = 1;
3364
            $dx    = 1;
3365
            $i = 0;
3366
3367
            while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
3368
                // Apply Newton-Raphson step
3369
                $result = self::TDIST($x, $degrees, 2);
3370
                $error = $result - $probability;
3371
                if ($error == 0.0) {
3372
                    $dx = 0;
3373
                } elseif ($error < 0.0) {
3374
                    $xLo = $x;
3375
                } else {
3376
                    $xHi = $x;
3377
                }
3378
                // Avoid division by zero
3379
                if ($result != 0.0) {
3380
                    $dx = $error / $result;
3381
                    $xNew = $x - $dx;
3382
                }
3383
                // If the NR fails to converge (which for example may be the
3384
                // case if the initial guess is too rough) we apply a bisection
3385
                // step to determine a more narrow interval around the root.
3386
                if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
3387
                    $xNew = ($xLo + $xHi) / 2;
3388
                    $dx = $xNew - $x;
3389
                }
3390
                $x = $xNew;
3391
            }
3392
            if ($i == MAX_ITERATIONS) {
3393
                return Functions::NA();
3394
            }
3395
            return round($x, 12);
3396
        }
3397
        return Functions::VALUE();
3398
    }
3399
3400
3401
    /**
3402
     * TREND
3403
     *
3404
     * Returns values along a linear Trend
3405
     *
3406
     * @param    array of mixed        Data Series Y
3407
     * @param    array of mixed        Data Series X
3408
     * @param    array of mixed        Values of X for which we want to find Y
3409
     * @param    boolean                A logical value specifying whether to force the intersect to equal 0.
3410
     * @return    array of float
3411
     */
3412 View Code Duplication
    public static function TREND($yValues, $xValues = array(), $newValues = array(), $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...
3413
    {
3414
        $yValues = Functions::flattenArray($yValues);
3415
        $xValues = Functions::flattenArray($xValues);
3416
        $newValues = Functions::flattenArray($newValues);
3417
        $const = (is_null($const)) ? true : (boolean) Functions::flattenSingleValue($const);
3418
3419
        $bestFitLinear = \PhpSpreadsheet\Shared\trend\trend::calculate(\PhpSpreadsheet\Shared\trend\trend::TREND_LINEAR, $yValues, $xValues, $const);
3420
        if (empty($newValues)) {
3421
            $newValues = $bestFitLinear->getXValues();
3422
        }
3423
3424
        $returnArray = array();
3425
        foreach ($newValues as $xValue) {
3426
            $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
3427
        }
3428
3429
        return $returnArray;
3430
    }
3431
3432
3433
    /**
3434
     * TRIMMEAN
3435
     *
3436
     * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
3437
     *        taken by excluding a percentage of data points from the top and bottom tails
3438
     *        of a data set.
3439
     *
3440
     * Excel Function:
3441
     *        TRIMEAN(value1[,value2[, ...]], $discard)
3442
     *
3443
     * @access    public
3444
     * @category Statistical Functions
3445
     * @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...
3446
     * @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...
3447
     * @return    float
3448
     */
3449
    public static function TRIMMEAN()
3450
    {
3451
        $aArgs = Functions::flattenArray(func_get_args());
3452
3453
        // Calculate
3454
        $percent = array_pop($aArgs);
3455
3456
        if ((is_numeric($percent)) && (!is_string($percent))) {
3457
            if (($percent < 0) || ($percent > 1)) {
3458
                return Functions::NAN();
3459
            }
3460
            $mArgs = array();
3461
            foreach ($aArgs as $arg) {
3462
                // Is it a numeric value?
3463
                if ((is_numeric($arg)) && (!is_string($arg))) {
3464
                    $mArgs[] = $arg;
3465
                }
3466
            }
3467
            $discard = floor(self::COUNT($mArgs) * $percent / 2);
3468
            sort($mArgs);
3469
            for ($i=0; $i < $discard; ++$i) {
3470
                array_pop($mArgs);
3471
                array_shift($mArgs);
3472
            }
3473
            return self::AVERAGE($mArgs);
3474
        }
3475
        return Functions::VALUE();
3476
    }
3477
3478
3479
    /**
3480
     * VARFunc
3481
     *
3482
     * Estimates variance based on a sample.
3483
     *
3484
     * Excel Function:
3485
     *        VAR(value1[,value2[, ...]])
3486
     *
3487
     * @access    public
3488
     * @category Statistical Functions
3489
     * @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...
3490
     * @return    float
3491
     */
3492 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...
3493
    {
3494
        $returnValue = Functions::DIV0();
3495
3496
        $summerA = $summerB = 0;
3497
3498
        // Loop through arguments
3499
        $aArgs = Functions::flattenArray(func_get_args());
3500
        $aCount = 0;
3501
        foreach ($aArgs as $arg) {
3502
            if (is_bool($arg)) {
3503
                $arg = (integer) $arg;
3504
            }
3505
            // Is it a numeric value?
3506
            if ((is_numeric($arg)) && (!is_string($arg))) {
3507
                $summerA += ($arg * $arg);
3508
                $summerB += $arg;
3509
                ++$aCount;
3510
            }
3511
        }
3512
3513
        if ($aCount > 1) {
3514
            $summerA *= $aCount;
3515
            $summerB *= $summerB;
3516
            $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3517
        }
3518
        return $returnValue;
3519
    }
3520
3521
3522
    /**
3523
     * VARA
3524
     *
3525
     * Estimates variance based on a sample, including numbers, text, and logical values
3526
     *
3527
     * Excel Function:
3528
     *        VARA(value1[,value2[, ...]])
3529
     *
3530
     * @access    public
3531
     * @category Statistical Functions
3532
     * @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...
3533
     * @return    float
3534
     */
3535 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...
3536
    {
3537
        $returnValue = Functions::DIV0();
3538
3539
        $summerA = $summerB = 0;
3540
3541
        // Loop through arguments
3542
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3543
        $aCount = 0;
3544
        foreach ($aArgs as $k => $arg) {
3545
            if ((is_string($arg)) &&
3546
                (Functions::isValue($k))) {
3547
                return Functions::VALUE();
3548
            } 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...
3549
                (!Functions::isMatrixValue($k))) {
3550
            } else {
3551
                // Is it a numeric value?
3552
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3553
                    if (is_bool($arg)) {
3554
                        $arg = (integer) $arg;
3555
                    } elseif (is_string($arg)) {
3556
                        $arg = 0;
3557
                    }
3558
                    $summerA += ($arg * $arg);
3559
                    $summerB += $arg;
3560
                    ++$aCount;
3561
                }
3562
            }
3563
        }
3564
3565
        if ($aCount > 1) {
3566
            $summerA *= $aCount;
3567
            $summerB *= $summerB;
3568
            $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
3569
        }
3570
        return $returnValue;
3571
    }
3572
3573
3574
    /**
3575
     * VARP
3576
     *
3577
     * Calculates variance based on the entire population
3578
     *
3579
     * Excel Function:
3580
     *        VARP(value1[,value2[, ...]])
3581
     *
3582
     * @access    public
3583
     * @category Statistical Functions
3584
     * @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...
3585
     * @return    float
3586
     */
3587 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...
3588
    {
3589
        // Return value
3590
        $returnValue = Functions::DIV0();
3591
3592
        $summerA = $summerB = 0;
3593
3594
        // Loop through arguments
3595
        $aArgs = Functions::flattenArray(func_get_args());
3596
        $aCount = 0;
3597
        foreach ($aArgs as $arg) {
3598
            if (is_bool($arg)) {
3599
                $arg = (integer) $arg;
3600
            }
3601
            // Is it a numeric value?
3602
            if ((is_numeric($arg)) && (!is_string($arg))) {
3603
                $summerA += ($arg * $arg);
3604
                $summerB += $arg;
3605
                ++$aCount;
3606
            }
3607
        }
3608
3609
        if ($aCount > 0) {
3610
            $summerA *= $aCount;
3611
            $summerB *= $summerB;
3612
            $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3613
        }
3614
        return $returnValue;
3615
    }
3616
3617
3618
    /**
3619
     * VARPA
3620
     *
3621
     * Calculates variance based on the entire population, including numbers, text, and logical values
3622
     *
3623
     * Excel Function:
3624
     *        VARPA(value1[,value2[, ...]])
3625
     *
3626
     * @access    public
3627
     * @category Statistical Functions
3628
     * @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...
3629
     * @return    float
3630
     */
3631 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...
3632
    {
3633
        $returnValue = Functions::DIV0();
3634
3635
        $summerA = $summerB = 0;
3636
3637
        // Loop through arguments
3638
        $aArgs = Functions::flattenArrayIndexed(func_get_args());
3639
        $aCount = 0;
3640
        foreach ($aArgs as $k => $arg) {
3641
            if ((is_string($arg)) &&
3642
                (Functions::isValue($k))) {
3643
                return Functions::VALUE();
3644
            } 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...
3645
                (!Functions::isMatrixValue($k))) {
3646
            } else {
3647
                // Is it a numeric value?
3648
                if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
3649
                    if (is_bool($arg)) {
3650
                        $arg = (integer) $arg;
3651
                    } elseif (is_string($arg)) {
3652
                        $arg = 0;
3653
                    }
3654
                    $summerA += ($arg * $arg);
3655
                    $summerB += $arg;
3656
                    ++$aCount;
3657
                }
3658
            }
3659
        }
3660
3661
        if ($aCount > 0) {
3662
            $summerA *= $aCount;
3663
            $summerB *= $summerB;
3664
            $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
3665
        }
3666
        return $returnValue;
3667
    }
3668
3669
3670
    /**
3671
     * WEIBULL
3672
     *
3673
     * Returns the Weibull distribution. Use this distribution in reliability
3674
     * analysis, such as calculating a device's mean time to failure.
3675
     *
3676
     * @param    float        $value
3677
     * @param    float        $alpha        Alpha Parameter
3678
     * @param    float        $beta        Beta Parameter
3679
     * @param    boolean        $cumulative
3680
     * @return    float
3681
     *
3682
     */
3683
    public static function WEIBULL($value, $alpha, $beta, $cumulative)
3684
    {
3685
        $value = Functions::flattenSingleValue($value);
3686
        $alpha = Functions::flattenSingleValue($alpha);
3687
        $beta  = Functions::flattenSingleValue($beta);
3688
3689
        if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) {
3690
            if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) {
3691
                return Functions::NAN();
3692
            }
3693
            if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
3694
                if ($cumulative) {
3695
                    return 1 - exp(0 - pow($value / $beta, $alpha));
3696
                } else {
3697
                    return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha));
3698
                }
3699
            }
3700
        }
3701
        return Functions::VALUE();
3702
    }
3703
3704
3705
    /**
3706
     * ZTEST
3707
     *
3708
     * Returns the Weibull distribution. Use this distribution in reliability
3709
     * analysis, such as calculating a device's mean time to failure.
3710
     *
3711
     * @param    float        $dataSet
3712
     * @param    float        $m0        Alpha Parameter
3713
     * @param    float        $sigma    Beta Parameter
3714
     * @param    boolean        $cumulative
0 ignored issues
show
Bug introduced by
There is no parameter named $cumulative. 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...
3715
     * @return    float
3716
     *
3717
     */
3718
    public static function ZTEST($dataSet, $m0, $sigma = null)
3719
    {
3720
        $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...
3721
        $m0      = Functions::flattenSingleValue($m0);
3722
        $sigma   = Functions::flattenSingleValue($sigma);
3723
3724
        if (is_null($sigma)) {
3725
            $sigma = self::STDEV($dataSet);
3726
        }
3727
        $n = count($dataSet);
3728
3729
        return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / SQRT($n)));
3730
    }
3731
}
3732