Failed Conditions
Push — master ( 59326f...691b68 )
by Adrien
25:51 queued 17:10
created

MathTrig::SUMSQ()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 13
ccs 6
cts 6
cp 1
crap 4
rs 9.2
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation;
4
5
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
6
use PhpOffice\PhpSpreadsheet\Shared\JAMA\Matrix;
7
8
class MathTrig
9
{
10
    //
11
    //    Private method to return an array of the factors of the input value
12
    //
13 12
    private static function factors($value)
14
    {
15 12
        $startVal = floor(sqrt($value));
16
17 12
        $factorArray = [];
18 12
        for ($i = $startVal; $i > 1; --$i) {
19 11
            if (($value % $i) == 0) {
20 8
                $factorArray = array_merge($factorArray, self::factors($value / $i));
21 8
                $factorArray = array_merge($factorArray, self::factors($i));
22 8
                if ($i <= sqrt($value)) {
23 8
                    break;
24
                }
25
            }
26
        }
27 12
        if (!empty($factorArray)) {
28 8
            rsort($factorArray);
29
30 8
            return $factorArray;
31
        }
32
33 12
        return [(int) $value];
34
    }
35
36 5
    private static function romanCut($num, $n)
37
    {
38 5
        return ($num - ($num % $n)) / $n;
39
    }
40
41
    /**
42
     * ATAN2.
43
     *
44
     * This function calculates the arc tangent of the two variables x and y. It is similar to
45
     *        calculating the arc tangent of y ÷ x, except that the signs of both arguments are used
46
     *        to determine the quadrant of the result.
47
     * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a
48
     *        point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between
49
     *        -pi and pi, excluding -pi.
50
     *
51
     * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard
52
     *        PHP atan2() function, so we need to reverse them here before calling the PHP atan() function.
53
     *
54
     * Excel Function:
55
     *        ATAN2(xCoordinate,yCoordinate)
56
     *
57
     * @category Mathematical and Trigonometric Functions
58
     *
59
     * @param float $xCoordinate the x-coordinate of the point
60
     * @param float $yCoordinate the y-coordinate of the point
61
     *
62
     * @return float the inverse tangent of the specified x- and y-coordinates
63
     */
64 16
    public static function ATAN2($xCoordinate = null, $yCoordinate = null)
65
    {
66 16
        $xCoordinate = Functions::flattenSingleValue($xCoordinate);
67 16
        $yCoordinate = Functions::flattenSingleValue($yCoordinate);
68
69 16
        $xCoordinate = ($xCoordinate !== null) ? $xCoordinate : 0.0;
70 16
        $yCoordinate = ($yCoordinate !== null) ? $yCoordinate : 0.0;
71
72 16
        if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
73 16
            ((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) {
74 15
            $xCoordinate = (float) $xCoordinate;
75 15
            $yCoordinate = (float) $yCoordinate;
76
77 15
            if (($xCoordinate == 0) && ($yCoordinate == 0)) {
78 1
                return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
79
            }
80
81 14
            return atan2($yCoordinate, $xCoordinate);
82
        }
83
84 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
85
    }
86
87
    /**
88
     * CEILING.
89
     *
90
     * Returns number rounded up, away from zero, to the nearest multiple of significance.
91
     *        For example, if you want to avoid using pennies in your prices and your product is
92
     *        priced at $4.42, use the formula =CEILING(4.42,0.05) to round prices up to the
93
     *        nearest nickel.
94
     *
95
     * Excel Function:
96
     *        CEILING(number[,significance])
97
     *
98
     * @category Mathematical and Trigonometric Functions
99
     *
100
     * @param float $number the number you want to round
101
     * @param float $significance the multiple to which you want to round
102
     *
103
     * @return float Rounded Number
104
     */
105 43 View Code Duplication
    public static function CEILING($number, $significance = null)
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...
106
    {
107 43
        $number = Functions::flattenSingleValue($number);
108 43
        $significance = Functions::flattenSingleValue($significance);
109
110 43
        if (($significance === null) &&
111 43
            (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
112
            $significance = $number / abs($number);
113
        }
114
115 43
        if ((is_numeric($number)) && (is_numeric($significance))) {
116 41
            if (($number == 0.0) || ($significance == 0.0)) {
117 3
                return 0.0;
118 38
            } elseif (self::SIGN($number) == self::SIGN($significance)) {
119 35
                return ceil($number / $significance) * $significance;
120
            }
121
122 3
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
123
        }
124
125 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
126
    }
127
128
    /**
129
     * COMBIN.
130
     *
131
     * Returns the number of combinations for a given number of items. Use COMBIN to
132
     *        determine the total possible number of groups for a given number of items.
133
     *
134
     * Excel Function:
135
     *        COMBIN(numObjs,numInSet)
136
     *
137
     * @category Mathematical and Trigonometric Functions
138
     *
139
     * @param int $numObjs Number of different objects
140
     * @param int $numInSet Number of objects in each combination
141
     *
142
     * @return int Number of combinations
143
     */
144 24
    public static function COMBIN($numObjs, $numInSet)
145
    {
146 24
        $numObjs = Functions::flattenSingleValue($numObjs);
147 24
        $numInSet = Functions::flattenSingleValue($numInSet);
148
149 24
        if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
150 23
            if ($numObjs < $numInSet) {
151 3
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
152 20
            } elseif ($numInSet < 0) {
153 2
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
154
            }
155
156 18
            return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
157
        }
158
159 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
160
    }
161
162
    /**
163
     * EVEN.
164
     *
165
     * Returns number rounded up to the nearest even integer.
166
     * You can use this function for processing items that come in twos. For example,
167
     *        a packing crate accepts rows of one or two items. The crate is full when
168
     *        the number of items, rounded up to the nearest two, matches the crate's
169
     *        capacity.
170
     *
171
     * Excel Function:
172
     *        EVEN(number)
173
     *
174
     * @category Mathematical and Trigonometric Functions
175
     *
176
     * @param float $number Number to round
177
     *
178
     * @return int Rounded Number
179
     */
180 25
    public static function EVEN($number)
181
    {
182 25
        $number = Functions::flattenSingleValue($number);
183
184 25
        if ($number === null) {
185 1
            return 0;
186 24
        } elseif (is_bool($number)) {
187 2
            $number = (int) $number;
188
        }
189
190 24
        if (is_numeric($number)) {
191 23
            $significance = 2 * self::SIGN($number);
192
193 23
            return (int) self::CEILING($number, $significance);
194
        }
195
196 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
197
    }
198
199
    /**
200
     * FACT.
201
     *
202
     * Returns the factorial of a number.
203
     * The factorial of a number is equal to 1*2*3*...* number.
204
     *
205
     * Excel Function:
206
     *        FACT(factVal)
207
     *
208
     * @category Mathematical and Trigonometric Functions
209
     *
210
     * @param float $factVal Factorial Value
211
     *
212
     * @return int Factorial
213
     */
214 145
    public static function FACT($factVal)
215
    {
216 145
        $factVal = Functions::flattenSingleValue($factVal);
217
218 145
        if (is_numeric($factVal)) {
219 144
            if ($factVal < 0) {
220 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
221
            }
222 143
            $factLoop = floor($factVal);
223 143
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
224
                if ($factVal > $factLoop) {
225
                    return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
226
                }
227
            }
228
229 143
            $factorial = 1;
230 143
            while ($factLoop > 1) {
231 71
                $factorial *= $factLoop--;
232
            }
233
234 143
            return $factorial;
235
        }
236
237 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
238
    }
239
240
    /**
241
     * FACTDOUBLE.
242
     *
243
     * Returns the double factorial of a number.
244
     *
245
     * Excel Function:
246
     *        FACTDOUBLE(factVal)
247
     *
248
     * @category Mathematical and Trigonometric Functions
249
     *
250
     * @param float $factVal Factorial Value
251
     *
252
     * @return int Double Factorial
253
     */
254 8
    public static function FACTDOUBLE($factVal)
255
    {
256 8
        $factLoop = Functions::flattenSingleValue($factVal);
257
258 8
        if (is_numeric($factLoop)) {
259 7
            $factLoop = floor($factLoop);
260 7
            if ($factVal < 0) {
261 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
262
            }
263 6
            $factorial = 1;
264 6
            while ($factLoop > 1) {
265 5
                $factorial *= $factLoop--;
266 5
                --$factLoop;
267
            }
268
269 6
            return $factorial;
270
        }
271
272 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
273
    }
274
275
    /**
276
     * FLOOR.
277
     *
278
     * Rounds number down, toward zero, to the nearest multiple of significance.
279
     *
280
     * Excel Function:
281
     *        FLOOR(number[,significance])
282
     *
283
     * @category Mathematical and Trigonometric Functions
284
     *
285
     * @param float $number Number to round
286
     * @param float $significance Significance
287
     *
288
     * @return float Rounded Number
289
     */
290 11 View Code Duplication
    public static function FLOOR($number, $significance = null)
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...
291
    {
292 11
        $number = Functions::flattenSingleValue($number);
293 11
        $significance = Functions::flattenSingleValue($significance);
294
295 11
        if (($significance === null) &&
296 11
            (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) {
297
            $significance = $number / abs($number);
298
        }
299
300 11
        if ((is_numeric($number)) && (is_numeric($significance))) {
301 9
            if ($significance == 0.0) {
302 1
                return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
303 8
            } elseif ($number == 0.0) {
304
                return 0.0;
305 8
            } elseif (self::SIGN($number) == self::SIGN($significance)) {
306 6
                return floor($number / $significance) * $significance;
307
            }
308
309 2
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
310
        }
311
312 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
313
    }
314
315 25
    private static function evaluateGCD($a, $b)
316
    {
317 25
        return $b ? self::evaluateGCD($b, $a % $b) : $a;
318
    }
319
320
    /**
321
     * GCD.
322
     *
323
     * Returns the greatest common divisor of a series of numbers.
324
     * The greatest common divisor is the largest integer that divides both
325
     *        number1 and number2 without a remainder.
326
     *
327
     * Excel Function:
328
     *        GCD(number1[,number2[, ...]])
329
     *
330
     * @category Mathematical and Trigonometric Functions
331
     *
332
     * @param mixed ...$args Data values
333
     *
334
     * @return int Greatest Common Divisor
335
     */
336 27
    public static function GCD(...$args)
337
    {
338 27
        $args = Functions::flattenArray($args);
339
        // Loop through arguments
340 27
        foreach (Functions::flattenArray($args) as $value) {
341 27
            if (!is_numeric($value)) {
342 1
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
343 27
            } elseif ($value < 0) {
344 27
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
345
            }
346
        }
347
348 25
        $gcd = (int) array_pop($args);
349
        do {
350 25
            $gcd = self::evaluateGCD($gcd, (int) array_pop($args));
351 25
        } while (!empty($args));
352
353 25
        return $gcd;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $gcd also could return the type mixed which is incompatible with the documented return type integer.
Loading history...
354
    }
355
356
    /**
357
     * INT.
358
     *
359
     * Casts a floating point value to an integer
360
     *
361
     * Excel Function:
362
     *        INT(number)
363
     *
364
     * @category Mathematical and Trigonometric Functions
365
     *
366
     * @param float $number Number to cast to an integer
367
     *
368
     * @return int Integer value
369
     */
370 19
    public static function INT($number)
371
    {
372 19
        $number = Functions::flattenSingleValue($number);
373
374 19
        if ($number === null) {
375 1
            return 0;
376 18
        } elseif (is_bool($number)) {
377 2
            return (int) $number;
378
        }
379 16
        if (is_numeric($number)) {
380 15
            return (int) floor($number);
381
        }
382
383 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
384
    }
385
386
    /**
387
     * LCM.
388
     *
389
     * Returns the lowest common multiplier of a series of numbers
390
     * The least common multiple is the smallest positive integer that is a multiple
391
     * of all integer arguments number1, number2, and so on. Use LCM to add fractions
392
     * with different denominators.
393
     *
394
     * Excel Function:
395
     *        LCM(number1[,number2[, ...]])
396
     *
397
     * @category Mathematical and Trigonometric Functions
398
     *
399
     * @param mixed ...$args Data values
400
     *
401
     * @return int Lowest Common Multiplier
402
     */
403 12
    public static function LCM(...$args)
404
    {
405 12
        $returnValue = 1;
406 12
        $allPoweredFactors = [];
407
        // Loop through arguments
408 12
        foreach (Functions::flattenArray($args) as $value) {
409 12
            if (!is_numeric($value)) {
410 1
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
411
            }
412 12
            if ($value == 0) {
413 1
                return 0;
414 12
            } elseif ($value < 0) {
415 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
416
            }
417 12
            $myFactors = self::factors(floor($value));
418 12
            $myCountedFactors = array_count_values($myFactors);
419 12
            $myPoweredFactors = [];
420 12
            foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) {
421 12
                $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor, $myCountedPower);
422
            }
423 12
            foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
424 12
                if (isset($allPoweredFactors[$myPoweredValue])) {
425 6
                    if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
426 6
                        $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
427
                    }
428
                } else {
429 12
                    $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
430
                }
431
            }
432
        }
433 9
        foreach ($allPoweredFactors as $allPoweredFactor) {
434 9
            $returnValue *= (int) $allPoweredFactor;
435
        }
436
437 9
        return $returnValue;
438
    }
439
440
    /**
441
     * LOG_BASE.
442
     *
443
     * Returns the logarithm of a number to a specified base. The default base is 10.
444
     *
445
     * Excel Function:
446
     *        LOG(number[,base])
447
     *
448
     * @category Mathematical and Trigonometric Functions
449
     *
450
     * @param float $number The positive real number for which you want the logarithm
451
     * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10.
452
     *
453
     * @return float
454
     */
455 69
    public static function logBase($number = null, $base = 10)
456
    {
457 69
        $number = Functions::flattenSingleValue($number);
458 69
        $base = ($base === null) ? 10 : (float) Functions::flattenSingleValue($base);
459
460 69
        if ((!is_numeric($base)) || (!is_numeric($number))) {
461 2
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
462
        }
463 67
        if (($base <= 0) || ($number <= 0)) {
464 18
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
465
        }
466
467 49
        return log($number, $base);
468
    }
469
470
    /**
471
     * MDETERM.
472
     *
473
     * Returns the matrix determinant of an array.
474
     *
475
     * Excel Function:
476
     *        MDETERM(array)
477
     *
478
     * @category Mathematical and Trigonometric Functions
479
     *
480
     * @param array $matrixValues A matrix of values
481
     *
482
     * @return float
483
     */
484 14 View Code Duplication
    public static function MDETERM($matrixValues)
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...
485
    {
486 14
        $matrixData = [];
487 14
        if (!is_array($matrixValues)) {
488
            $matrixValues = [[$matrixValues]];
489
        }
490
491 14
        $row = $maxColumn = 0;
492 14
        foreach ($matrixValues as $matrixRow) {
493 14
            if (!is_array($matrixRow)) {
494
                $matrixRow = [$matrixRow];
495
            }
496 14
            $column = 0;
497 14
            foreach ($matrixRow as $matrixCell) {
498 14
                if ((is_string($matrixCell)) || ($matrixCell === null)) {
499 1
                    return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
500
                }
501 14
                $matrixData[$column][$row] = $matrixCell;
502 14
                ++$column;
503
            }
504 14
            if ($column > $maxColumn) {
505 14
                $maxColumn = $column;
506
            }
507 14
            ++$row;
508
        }
509 13
        if ($row != $maxColumn) {
510 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
511
        }
512
513
        try {
514 12
            $matrix = new Matrix($matrixData);
515
516 12
            return $matrix->det();
517
        } catch (PhpSpreadsheetException $ex) {
518
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
519
        }
520
    }
521
522
    /**
523
     * MINVERSE.
524
     *
525
     * Returns the inverse matrix for the matrix stored in an array.
526
     *
527
     * Excel Function:
528
     *        MINVERSE(array)
529
     *
530
     * @category Mathematical and Trigonometric Functions
531
     *
532
     * @param array $matrixValues A matrix of values
533
     *
534
     * @return array
535
     */
536 View Code Duplication
    public static function MINVERSE($matrixValues)
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...
537
    {
538
        $matrixData = [];
539
        if (!is_array($matrixValues)) {
540
            $matrixValues = [[$matrixValues]];
541
        }
542
543
        $row = $maxColumn = 0;
544
        foreach ($matrixValues as $matrixRow) {
545
            if (!is_array($matrixRow)) {
546
                $matrixRow = [$matrixRow];
547
            }
548
            $column = 0;
549
            foreach ($matrixRow as $matrixCell) {
550
                if ((is_string($matrixCell)) || ($matrixCell === null)) {
551
                    return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
552
                }
553
                $matrixData[$column][$row] = $matrixCell;
554
                ++$column;
555
            }
556
            if ($column > $maxColumn) {
557
                $maxColumn = $column;
558
            }
559
            ++$row;
560
        }
561
        foreach ($matrixValues as $matrixRow) {
562
            if (count($matrixRow) != $maxColumn) {
563
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
564
            }
565
        }
566
567
        try {
568
            $matrix = new Matrix($matrixData);
569
570
            return $matrix->inverse()->getArray();
571
        } catch (PhpSpreadsheetException $ex) {
572
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
573
        }
574
    }
575
576
    /**
577
     * MMULT.
578
     *
579
     * @param array $matrixData1 A matrix of values
580
     * @param array $matrixData2 A matrix of values
581
     *
582
     * @return array
583
     */
584
    public static function MMULT($matrixData1, $matrixData2)
585
    {
586
        $matrixAData = $matrixBData = [];
587
        if (!is_array($matrixData1)) {
588
            $matrixData1 = [[$matrixData1]];
589
        }
590
        if (!is_array($matrixData2)) {
591
            $matrixData2 = [[$matrixData2]];
592
        }
593
594
        try {
595
            $rowA = 0;
596 View Code Duplication
            foreach ($matrixData1 as $matrixRow) {
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...
597
                if (!is_array($matrixRow)) {
598
                    $matrixRow = [$matrixRow];
599
                }
600
                $columnA = 0;
601
                foreach ($matrixRow as $matrixCell) {
602
                    if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
603
                        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
604
                    }
605
                    $matrixAData[$rowA][$columnA] = $matrixCell;
606
                    ++$columnA;
607
                }
608
                ++$rowA;
609
            }
610
            $matrixA = new Matrix($matrixAData);
611
            $rowB = 0;
612 View Code Duplication
            foreach ($matrixData2 as $matrixRow) {
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...
613
                if (!is_array($matrixRow)) {
614
                    $matrixRow = [$matrixRow];
615
                }
616
                $columnB = 0;
617
                foreach ($matrixRow as $matrixCell) {
618
                    if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
619
                        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
620
                    }
621
                    $matrixBData[$rowB][$columnB] = $matrixCell;
622
                    ++$columnB;
623
                }
624
                ++$rowB;
625
            }
626
            $matrixB = new Matrix($matrixBData);
627
628
            if ($columnA != $rowB) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $columnA seems to be defined by a foreach iteration on line 596. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
629
                return Functions::VALUE();
630
            }
631
632
            return $matrixA->times($matrixB)->getArray();
633
        } catch (PhpSpreadsheetException $ex) {
634
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type array.
Loading history...
635
        }
636
    }
637
638
    /**
639
     * MOD.
640
     *
641
     * @param int $a Dividend
642
     * @param int $b Divisor
643
     *
644
     * @return int Remainder
645
     */
646 10
    public static function MOD($a = 1, $b = 1)
647
    {
648 10
        $a = (float) Functions::flattenSingleValue($a);
649 10
        $b = (float) Functions::flattenSingleValue($b);
650
651 10
        if ($b == 0.0) {
652 1
            return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type integer.
Loading history...
653 9
        } elseif (($a < 0.0) && ($b > 0.0)) {
654 1
            return $b - fmod(abs($a), $b);
655 8
        } elseif (($a > 0.0) && ($b < 0.0)) {
656 2
            return $b + fmod($a, abs($b));
657
        }
658
659 6
        return fmod($a, $b);
660
    }
661
662
    /**
663
     * MROUND.
664
     *
665
     * Rounds a number to the nearest multiple of a specified value
666
     *
667
     * @param float $number Number to round
668
     * @param int $multiple Multiple to which you want to round $number
669
     *
670
     * @return float Rounded Number
671
     */
672 13
    public static function MROUND($number, $multiple)
673
    {
674 13
        $number = Functions::flattenSingleValue($number);
675 13
        $multiple = Functions::flattenSingleValue($multiple);
676
677 13
        if ((is_numeric($number)) && (is_numeric($multiple))) {
678 11
            if ($multiple == 0) {
679 1
                return 0;
680
            }
681 10
            if ((self::SIGN($number)) == (self::SIGN($multiple))) {
682 9
                $multiplier = 1 / $multiple;
683
684 9
                return round($number * $multiplier) / $multiplier;
685
            }
686
687 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
688
        }
689
690 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
691
    }
692
693
    /**
694
     * MULTINOMIAL.
695
     *
696
     * Returns the ratio of the factorial of a sum of values to the product of factorials.
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\of was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
697
     *
698
     * @param array of mixed Data Series
699
     *
700
     * @return float
701
     */
702 2
    public static function MULTINOMIAL(...$args)
703
    {
704 2
        $summer = 0;
705 2
        $divisor = 1;
706
        // Loop through arguments
707 2
        foreach (Functions::flattenArray($args) as $arg) {
708
            // Is it a numeric value?
709 2
            if (is_numeric($arg)) {
710 2
                if ($arg < 1) {
711
                    return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
712
                }
713 2
                $summer += floor($arg);
714 2
                $divisor *= self::FACT($arg);
715
            } else {
716 2
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
717
            }
718
        }
719
720
        // Return
721 2
        if ($summer > 0) {
722 2
            $summer = self::FACT($summer);
723
724 2
            return $summer / $divisor;
725
        }
726
727
        return 0;
728
    }
729
730
    /**
731
     * ODD.
732
     *
733
     * Returns number rounded up to the nearest odd integer.
734
     *
735
     * @param float $number Number to round
736
     *
737
     * @return int Rounded Number
738
     */
739 13
    public static function ODD($number)
740
    {
741 13
        $number = Functions::flattenSingleValue($number);
742
743 13
        if ($number === null) {
744 1
            return 1;
745 12
        } elseif (is_bool($number)) {
746 2
            return 1;
747 10
        } elseif (is_numeric($number)) {
748 9
            $significance = self::SIGN($number);
749 9
            if ($significance == 0) {
750 1
                return 1;
751
            }
752
753 8
            $result = self::CEILING($number, $significance);
754 8
            if ($result == self::EVEN($result)) {
755 5
                $result += $significance;
756
            }
757
758 8
            return (int) $result;
759
        }
760
761 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
762
    }
763
764
    /**
765
     * POWER.
766
     *
767
     * Computes x raised to the power y.
768
     *
769
     * @param float $x
770
     * @param float $y
771
     *
772
     * @return float
773
     */
774 81
    public static function POWER($x = 0, $y = 2)
775
    {
776 81
        $x = Functions::flattenSingleValue($x);
777 81
        $y = Functions::flattenSingleValue($y);
778
779
        // Validate parameters
780 81
        if ($x == 0.0 && $y == 0.0) {
781 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
782 80
        } elseif ($x == 0.0 && $y < 0.0) {
783 2
            return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
784
        }
785
786
        // Return
787 78
        $result = pow($x, $y);
788
789 78
        return (!is_nan($result) && !is_infinite($result)) ? $result : Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! is_nan($result)...lation\Functions::NAN() also could return the type string which is incompatible with the documented return type double.
Loading history...
790
    }
791
792
    /**
793
     * PRODUCT.
794
     *
795
     * PRODUCT returns the product of all the values and cells referenced in the argument list.
796
     *
797
     * Excel Function:
798
     *        PRODUCT(value1[,value2[, ...]])
799
     *
800
     * @category Mathematical and Trigonometric Functions
801
     *
802
     * @param mixed ...$args Data values
803
     *
804
     * @return float
805
     */
806 8 View Code Duplication
    public static function PRODUCT(...$args)
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...
807
    {
808
        // Return value
809 8
        $returnValue = null;
810
811
        // Loop through arguments
812 8
        foreach (Functions::flattenArray($args) as $arg) {
813
            // Is it a numeric value?
814 8
            if ((is_numeric($arg)) && (!is_string($arg))) {
815 8
                if ($returnValue === null) {
816 8
                    $returnValue = $arg;
817
                } else {
818 8
                    $returnValue *= $arg;
819
                }
820
            }
821
        }
822
823
        // Return
824 8
        if ($returnValue === null) {
825
            return 0;
826
        }
827
828 8
        return $returnValue;
829
    }
830
831
    /**
832
     * QUOTIENT.
833
     *
834
     * QUOTIENT function returns the integer portion of a division. Numerator is the divided number
835
     *        and denominator is the divisor.
836
     *
837
     * Excel Function:
838
     *        QUOTIENT(value1[,value2[, ...]])
839
     *
840
     * @category Mathematical and Trigonometric Functions
841
     *
842
     * @param mixed ...$args Data values
843
     *
844
     * @return float
845
     */
846 6
    public static function QUOTIENT(...$args)
847
    {
848
        // Return value
849 6
        $returnValue = null;
850
851
        // Loop through arguments
852 6
        foreach (Functions::flattenArray($args) as $arg) {
853
            // Is it a numeric value?
854 6
            if ((is_numeric($arg)) && (!is_string($arg))) {
855 6
                if ($returnValue === null) {
856 6
                    $returnValue = ($arg == 0) ? 0 : $arg;
857
                } else {
858 6
                    if (($returnValue == 0) || ($arg == 0)) {
859
                        $returnValue = 0;
860
                    } else {
861 6
                        $returnValue /= $arg;
862
                    }
863
                }
864
            }
865
        }
866
867
        // Return
868 6
        return (int) $returnValue;
869
    }
870
871
    /**
872
     * RAND.
873
     *
874
     * @param int $min Minimal value
875
     * @param int $max Maximal value
876
     *
877
     * @return int Random number
878
     */
879 3
    public static function RAND($min = 0, $max = 0)
880
    {
881 3
        $min = Functions::flattenSingleValue($min);
882 3
        $max = Functions::flattenSingleValue($max);
883
884 3
        if ($min == 0 && $max == 0) {
885 1
            return (mt_rand(0, 10000000)) / 10000000;
886
        }
887
888 3
        return mt_rand($min, $max);
889
    }
890
891 5
    public static function ROMAN($aValue, $style = 0)
892
    {
893 5
        $aValue = Functions::flattenSingleValue($aValue);
894 5
        $style = ($style === null) ? 0 : (int) Functions::flattenSingleValue($style);
0 ignored issues
show
Unused Code introduced by
The assignment to $style is dead and can be removed.
Loading history...
895 5 View Code Duplication
        if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) {
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...
896
            return Functions::VALUE();
897
        }
898 5
        $aValue = (int) $aValue;
899 5
        if ($aValue == 0) {
900
            return '';
901
        }
902
903 5
        $mill = ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM'];
904 5
        $cent = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'];
905 5
        $tens = ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'];
906 5
        $ones = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
907
908 5
        $roman = '';
909 5
        while ($aValue > 5999) {
910
            $roman .= 'M';
911
            $aValue -= 1000;
912
        }
913 5
        $m = self::romanCut($aValue, 1000);
914 5
        $aValue %= 1000;
915 5
        $c = self::romanCut($aValue, 100);
916 5
        $aValue %= 100;
917 5
        $t = self::romanCut($aValue, 10);
918 5
        $aValue %= 10;
919
920 5
        return $roman . $mill[$m] . $cent[$c] . $tens[$t] . $ones[$aValue];
921
    }
922
923
    /**
924
     * ROUNDUP.
925
     *
926
     * Rounds a number up to a specified number of decimal places
927
     *
928
     * @param float $number Number to round
929
     * @param int $digits Number of digits to which you want to round $number
930
     *
931
     * @return float Rounded Number
932
     */
933 14 View Code Duplication
    public static function ROUNDUP($number, $digits)
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...
934
    {
935 14
        $number = Functions::flattenSingleValue($number);
936 14
        $digits = Functions::flattenSingleValue($digits);
937
938 14
        if ((is_numeric($number)) && (is_numeric($digits))) {
939 12
            $significance = pow(10, (int) $digits);
940 12
            if ($number < 0.0) {
941 2
                return floor($number * $significance) / $significance;
942
            }
943
944 10
            return ceil($number * $significance) / $significance;
945
        }
946
947 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
948
    }
949
950
    /**
951
     * ROUNDDOWN.
952
     *
953
     * Rounds a number down to a specified number of decimal places
954
     *
955
     * @param float $number Number to round
956
     * @param int $digits Number of digits to which you want to round $number
957
     *
958
     * @return float Rounded Number
959
     */
960 14 View Code Duplication
    public static function ROUNDDOWN($number, $digits)
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...
961
    {
962 14
        $number = Functions::flattenSingleValue($number);
963 14
        $digits = Functions::flattenSingleValue($digits);
964
965 14
        if ((is_numeric($number)) && (is_numeric($digits))) {
966 12
            $significance = pow(10, (int) $digits);
967 12
            if ($number < 0.0) {
968 2
                return ceil($number * $significance) / $significance;
969
            }
970
971 10
            return floor($number * $significance) / $significance;
972
        }
973
974 2
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
975
    }
976
977
    /**
978
     * SERIESSUM.
979
     *
980
     * Returns the sum of a power series
981
     *
982
     * @param float $x Input value to the power series
983
     * @param float $n Initial power to which you want to raise $x
984
     * @param float $m Step by which to increase $n for each term in the series
985
     * @param array of mixed Data Series
986
     *
987
     * @return float
988
     */
989 2
    public static function SERIESSUM(...$args)
990
    {
991 2
        $returnValue = 0;
992
993
        // Loop through arguments
994 2
        $aArgs = Functions::flattenArray($args);
995
996 2
        $x = array_shift($aArgs);
997 2
        $n = array_shift($aArgs);
998 2
        $m = array_shift($aArgs);
999
1000 2
        if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
1001
            // Calculate
1002 2
            $i = 0;
1003 2
            foreach ($aArgs as $arg) {
1004
                // Is it a numeric value?
1005 2
                if ((is_numeric($arg)) && (!is_string($arg))) {
1006 2
                    $returnValue += $arg * pow($x, $n + ($m * $i++));
1007
                } else {
1008 2
                    return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1009
                }
1010
            }
1011
1012 2
            return $returnValue;
1013
        }
1014
1015
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1016
    }
1017
1018
    /**
1019
     * SIGN.
1020
     *
1021
     * Determines the sign of a number. Returns 1 if the number is positive, zero (0)
1022
     *        if the number is 0, and -1 if the number is negative.
1023
     *
1024
     * @param float $number Number to round
1025
     *
1026
     * @return int sign value
1027
     */
1028 72
    public static function SIGN($number)
1029
    {
1030 72
        $number = Functions::flattenSingleValue($number);
1031
1032 72
        if (is_bool($number)) {
1033 2
            return (int) $number;
1034
        }
1035 70
        if (is_numeric($number)) {
1036 69
            if ($number == 0.0) {
1037 4
                return 0;
1038
            }
1039
1040 65
            return $number / abs($number);
1041
        }
1042
1043 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
1044
    }
1045
1046
    /**
1047
     * SQRTPI.
1048
     *
1049
     * Returns the square root of (number * pi).
1050
     *
1051
     * @param float $number Number
1052
     *
1053
     * @return float Square Root of Number * Pi
1054
     */
1055 15 View Code Duplication
    public static function SQRTPI($number)
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...
1056
    {
1057 15
        $number = Functions::flattenSingleValue($number);
1058
1059 15
        if (is_numeric($number)) {
1060 14
            if ($number < 0) {
1061 3
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1062
            }
1063
1064 11
            return sqrt($number * M_PI);
1065
        }
1066
1067 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1068
    }
1069
1070
    protected static function filterHiddenArgs($cellReference, $args)
1071
    {
1072
        return array_filter(
1073
            $args,
1074
            function ($index) use ($cellReference) {
1075
                list(, $row, $column) = explode('.', $index);
1076
1077
                return $cellReference->getWorksheet()->getRowDimension($row)->getVisible() &&
1078
                    $cellReference->getWorksheet()->getColumnDimension($column)->getVisible();
1079
            },
1080
            ARRAY_FILTER_USE_KEY
1081
        );
1082
    }
1083
1084
    /**
1085
     * SUBTOTAL.
1086
     *
1087
     * Returns a subtotal in a list or database.
1088
     *
1089
     * @param int the number 1 to 11 that specifies which function to
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1090
     *                    use in calculating subtotals within a list
1091
     * @param array of mixed Data Series
1092
     *
1093
     * @return float
1094
     */
1095
    public static function SUBTOTAL(...$args)
1096
    {
1097
        $aArgs = Functions::flattenArrayIndexed($args);
1098
        $cellReference = array_pop($aArgs);
1099
        $subtotal = array_shift($aArgs);
1100
1101
        // Calculate
1102
        if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
1103
            if ($subtotal > 100) {
1104
                $aArgs = self::filterHiddenArgs($cellReference, $aArgs);
1105
                $subtotal = $subtotal - 100;
1106
            }
1107
1108
            switch ($subtotal) {
1109
                case 1:
1110
                    return Statistical::AVERAGE($aArgs);
1111
                case 2:
1112
                    return Statistical::COUNT($aArgs);
1113
                case 3:
1114
                    return Statistical::COUNTA($aArgs);
1115
                case 4:
1116
                    return Statistical::MAX($aArgs);
1117
                case 5:
1118
                    return Statistical::MIN($aArgs);
1119
                case 6:
1120
                    return self::PRODUCT($aArgs);
1121
                case 7:
1122
                    return Statistical::STDEV($aArgs);
1123
                case 8:
1124
                    return Statistical::STDEVP($aArgs);
1125
                case 9:
1126
                    return self::SUM($aArgs);
1127
                case 10:
1128
                    return Statistical::VARFunc($aArgs);
1129
                case 11:
1130
                    return Statistical::VARP($aArgs);
1131
            }
1132
        }
1133
1134
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1135
    }
1136
1137
    /**
1138
     * SUM.
1139
     *
1140
     * SUM computes the sum of all the values and cells referenced in the argument list.
1141
     *
1142
     * Excel Function:
1143
     *        SUM(value1[,value2[, ...]])
1144
     *
1145
     * @category Mathematical and Trigonometric Functions
1146
     *
1147
     * @param mixed ...$args Data values
1148
     *
1149
     * @return float
1150
     */
1151 26
    public static function SUM(...$args)
1152
    {
1153 26
        $returnValue = 0;
1154
1155
        // Loop through the arguments
1156 26
        foreach (Functions::flattenArray($args) as $arg) {
1157
            // Is it a numeric value?
1158 26
            if ((is_numeric($arg)) && (!is_string($arg))) {
1159 26
                $returnValue += $arg;
1160
            }
1161
        }
1162
1163 26
        return $returnValue;
1164
    }
1165
1166
    /**
1167
     * SUMIF.
1168
     *
1169
     * Counts the number of cells that contain numbers within the list of arguments
1170
     *
1171
     * Excel Function:
1172
     *        SUMIF(value1[,value2[, ...]],condition)
1173
     *
1174
     * @category Mathematical and Trigonometric Functions
1175
     *
1176
     * @param mixed $aArgs Data values
1177
     * @param string $condition the criteria that defines which cells will be summed
1178
     * @param mixed $aArgs
1179
     * @param mixed $sumArgs
1180
     *
1181
     * @return float
1182
     */
1183 5
    public static function SUMIF($aArgs, $condition, $sumArgs = [])
1184
    {
1185 5
        $returnValue = 0;
1186
1187 5
        $aArgs = Functions::flattenArray($aArgs);
1188 5
        $sumArgs = Functions::flattenArray($sumArgs);
1189 5
        if (empty($sumArgs)) {
1190 1
            $sumArgs = $aArgs;
1191
        }
1192 5
        $condition = Functions::ifCondition($condition);
1193
        // Loop through arguments
1194 5
        foreach ($aArgs as $key => $arg) {
1195 5 View Code Duplication
            if (!is_numeric($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...
1196 4
                $arg = str_replace('"', '""', $arg);
1197 4
                $arg = Calculation::wrapResult(strtoupper($arg));
1198
            }
1199
1200 5
            $testCondition = '=' . $arg . $condition;
1201 5
            if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1202
                // Is it a value within our criteria
1203 5
                $returnValue += $sumArgs[$key];
1204
            }
1205
        }
1206
1207 5
        return $returnValue;
1208
    }
1209
1210
    /**
1211
     * SUMIFS.
1212
     *
1213
     *    Counts the number of cells that contain numbers within the list of arguments
1214
     *
1215
     *    Excel Function:
1216
     *        SUMIFS(value1[,value2[, ...]],condition)
1217
     *
1218
     *    @category Mathematical and Trigonometric Functions
1219
     *
1220
     * @param mixed $args Data values
1221
     * @param string $condition the criteria that defines which cells will be summed
1222
     *
1223
     * @return float
1224
     */
1225
    public static function SUMIFS(...$args)
1226
    {
1227
        $arrayList = $args;
1228
1229
        // Return value
1230
        $returnValue = 0;
1231
1232
        $sumArgs = Functions::flattenArray(array_shift($arrayList));
1233
1234
        while (count($arrayList) > 0) {
1235
            $aArgsArray[] = Functions::flattenArray(array_shift($arrayList));
1236
            $conditions[] = Functions::ifCondition(array_shift($arrayList));
1237
        }
1238
1239
        // Loop through each set of arguments and conditions
1240
        foreach ($conditions as $index => $condition) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $conditions does not seem to be defined for all execution paths leading up to this point.
Loading history...
1241
            $aArgs = $aArgsArray[$index];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $aArgsArray does not seem to be defined for all execution paths leading up to this point.
Loading history...
1242
1243
            // Loop through arguments
1244
            foreach ($aArgs as $key => $arg) {
1245
                if (!is_numeric($arg)) {
1246
                    $arg = Calculation::wrapResult(strtoupper($arg));
1247
                }
1248
                $testCondition = '=' . $arg . $condition;
1249
                if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1250
                    // Is it a value within our criteria
1251
                    $returnValue += $sumArgs[$key];
1252
                }
1253
            }
1254
        }
1255
1256
        // Return
1257
        return $returnValue;
1258
    }
1259
1260
    /**
1261
     * SUMPRODUCT.
1262
     *
1263
     * Excel Function:
1264
     *        SUMPRODUCT(value1[,value2[, ...]])
1265
     *
1266
     * @category Mathematical and Trigonometric Functions
1267
     *
1268
     * @param mixed ...$args Data values
1269
     *
1270
     * @return float
1271
     */
1272
    public static function SUMPRODUCT(...$args)
1273
    {
1274
        $arrayList = $args;
1275
1276
        $wrkArray = Functions::flattenArray(array_shift($arrayList));
1277
        $wrkCellCount = count($wrkArray);
1278
1279
        for ($i = 0; $i < $wrkCellCount; ++$i) {
1280
            if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
1281
                $wrkArray[$i] = 0;
1282
            }
1283
        }
1284
1285
        foreach ($arrayList as $matrixData) {
1286
            $array2 = Functions::flattenArray($matrixData);
1287
            $count = count($array2);
1288
            if ($wrkCellCount != $count) {
1289
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1290
            }
1291
1292
            foreach ($array2 as $i => $val) {
1293
                if ((!is_numeric($val)) || (is_string($val))) {
1294
                    $val = 0;
1295
                }
1296
                $wrkArray[$i] *= $val;
1297
            }
1298
        }
1299
1300
        return array_sum($wrkArray);
1301
    }
1302
1303
    /**
1304
     * SUMSQ.
1305
     *
1306
     * SUMSQ returns the sum of the squares of the arguments
1307
     *
1308
     * Excel Function:
1309
     *        SUMSQ(value1[,value2[, ...]])
1310
     *
1311
     * @category Mathematical and Trigonometric Functions
1312
     *
1313
     * @param mixed ...$args Data values
1314
     *
1315
     * @return float
1316
     */
1317 7
    public static function SUMSQ(...$args)
1318
    {
1319 7
        $returnValue = 0;
1320
1321
        // Loop through arguments
1322 7
        foreach (Functions::flattenArray($args) as $arg) {
1323
            // Is it a numeric value?
1324 7
            if ((is_numeric($arg)) && (!is_string($arg))) {
1325 7
                $returnValue += ($arg * $arg);
1326
            }
1327
        }
1328
1329 7
        return $returnValue;
1330
    }
1331
1332
    /**
1333
     * SUMX2MY2.
1334
     *
1335
     * @param mixed[] $matrixData1 Matrix #1
1336
     * @param mixed[] $matrixData2 Matrix #2
1337
     *
1338
     * @return float
1339
     */
1340 View Code Duplication
    public static function SUMX2MY2($matrixData1, $matrixData2)
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...
1341
    {
1342
        $array1 = Functions::flattenArray($matrixData1);
1343
        $array2 = Functions::flattenArray($matrixData2);
1344
        $count = min(count($array1), count($array2));
1345
1346
        $result = 0;
1347
        for ($i = 0; $i < $count; ++$i) {
1348
            if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1349
                ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1350
                $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
1351
            }
1352
        }
1353
1354
        return $result;
1355
    }
1356
1357
    /**
1358
     * SUMX2PY2.
1359
     *
1360
     * @param mixed[] $matrixData1 Matrix #1
1361
     * @param mixed[] $matrixData2 Matrix #2
1362
     *
1363
     * @return float
1364
     */
1365 View Code Duplication
    public static function SUMX2PY2($matrixData1, $matrixData2)
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...
1366
    {
1367
        $array1 = Functions::flattenArray($matrixData1);
1368
        $array2 = Functions::flattenArray($matrixData2);
1369
        $count = min(count($array1), count($array2));
1370
1371
        $result = 0;
1372
        for ($i = 0; $i < $count; ++$i) {
1373
            if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1374
                ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1375
                $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
1376
            }
1377
        }
1378
1379
        return $result;
1380
    }
1381
1382
    /**
1383
     * SUMXMY2.
1384
     *
1385
     * @param mixed[] $matrixData1 Matrix #1
1386
     * @param mixed[] $matrixData2 Matrix #2
1387
     *
1388
     * @return float
1389
     */
1390 View Code Duplication
    public static function SUMXMY2($matrixData1, $matrixData2)
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...
1391
    {
1392
        $array1 = Functions::flattenArray($matrixData1);
1393
        $array2 = Functions::flattenArray($matrixData2);
1394
        $count = min(count($array1), count($array2));
1395
1396
        $result = 0;
1397
        for ($i = 0; $i < $count; ++$i) {
1398
            if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1399
                ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1400
                $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
1401
            }
1402
        }
1403
1404
        return $result;
1405
    }
1406
1407
    /**
1408
     * TRUNC.
1409
     *
1410
     * Truncates value to the number of fractional digits by number_digits.
1411
     *
1412
     * @param float $value
1413
     * @param int $digits
1414
     *
1415
     * @return float Truncated value
1416
     */
1417 19
    public static function TRUNC($value = 0, $digits = 0)
1418
    {
1419 19
        $value = Functions::flattenSingleValue($value);
1420 19
        $digits = Functions::flattenSingleValue($digits);
1421
1422
        // Validate parameters
1423 19
        if ((!is_numeric($value)) || (!is_numeric($digits))) {
1424 2
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1425
        }
1426 17
        $digits = floor($digits);
1427
1428
        // Truncate
1429 17
        $adjust = pow(10, $digits);
1430
1431 17
        if (($digits > 0) && (rtrim((int) ((abs($value) - abs((int) $value)) * $adjust), '0') < $adjust / 10)) {
1432 2
            return $value;
1433
        }
1434
1435 15
        return ((int) ($value * $adjust)) / $adjust;
1436
    }
1437
}
1438