Total Complexity | 256 |
Total Lines | 1428 |
Duplicated Lines | 19.26 % |
Coverage | 66.23% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like MathTrig often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use MathTrig, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
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(); |
|
|
|||
79 | } |
||
80 | |||
81 | 14 | return atan2($yCoordinate, $xCoordinate); |
|
82 | } |
||
83 | |||
84 | 1 | return Functions::VALUE(); |
|
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) |
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(); |
|
123 | } |
||
124 | |||
125 | 2 | return Functions::VALUE(); |
|
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(); |
|
152 | 20 | } elseif ($numInSet < 0) { |
|
153 | 2 | return Functions::NAN(); |
|
154 | } |
||
155 | |||
156 | 18 | return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet); |
|
157 | } |
||
158 | |||
159 | 1 | return Functions::VALUE(); |
|
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(); |
|
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(); |
|
221 | } |
||
222 | 143 | $factLoop = floor($factVal); |
|
223 | 143 | if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { |
|
224 | if ($factVal > $factLoop) { |
||
225 | return Functions::NAN(); |
||
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(); |
|
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(); |
|
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(); |
|
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) |
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(); |
|
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(); |
|
310 | } |
||
311 | |||
312 | 2 | return Functions::VALUE(); |
|
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(); |
|
343 | 27 | } elseif ($value < 0) { |
|
344 | 27 | return Functions::NAN(); |
|
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; |
|
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(); |
|
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(); |
|
411 | } |
||
412 | 12 | if ($value == 0) { |
|
413 | 1 | return 0; |
|
414 | 12 | } elseif ($value < 0) { |
|
415 | 1 | return Functions::NAN(); |
|
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(); |
|
462 | } |
||
463 | 67 | if (($base <= 0) || ($number <= 0)) { |
|
464 | 18 | return Functions::NAN(); |
|
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) |
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) |
|
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(); |
||
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(); |
||
564 | } |
||
565 | } |
||
566 | |||
567 | try { |
||
568 | $matrix = new Matrix($matrixData); |
||
569 | |||
570 | return $matrix->inverse()->getArray(); |
||
571 | } catch (PhpSpreadsheetException $ex) { |
||
572 | return Functions::VALUE(); |
||
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) { |
|
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(); |
||
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) { |
|
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(); |
||
620 | } |
||
621 | $matrixBData[$rowB][$columnB] = $matrixCell; |
||
622 | ++$columnB; |
||
623 | } |
||
624 | ++$rowB; |
||
625 | } |
||
626 | $matrixB = new Matrix($matrixBData); |
||
627 | |||
628 | if ($columnA != $rowB) { |
||
629 | return Functions::VALUE(); |
||
630 | } |
||
631 | |||
632 | return $matrixA->times($matrixB)->getArray(); |
||
633 | } catch (PhpSpreadsheetException $ex) { |
||
634 | return Functions::VALUE(); |
||
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(); |
|
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(); |
|
688 | } |
||
689 | |||
690 | 2 | return Functions::VALUE(); |
|
691 | } |
||
692 | |||
693 | /** |
||
694 | * MULTINOMIAL. |
||
695 | * |
||
696 | * Returns the ratio of the factorial of a sum of values to the product of factorials. |
||
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(); |
||
712 | } |
||
713 | 2 | $summer += floor($arg); |
|
714 | 2 | $divisor *= self::FACT($arg); |
|
715 | } else { |
||
716 | 2 | return Functions::VALUE(); |
|
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(); |
|
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(); |
|
782 | 80 | } elseif ($x == 0.0 && $y < 0.0) { |
|
783 | 2 | return Functions::DIV0(); |
|
784 | } |
||
785 | |||
786 | // Return |
||
787 | 78 | $result = pow($x, $y); |
|
788 | |||
789 | 78 | return (!is_nan($result) && !is_infinite($result)) ? $result : Functions::NAN(); |
|
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) |
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); |
|
895 | 5 | View Code Duplication | if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) { |
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) |
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(); |
|
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) |
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(); |
|
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(); |
|
1009 | } |
||
1010 | } |
||
1011 | |||
1012 | 2 | return $returnValue; |
|
1013 | } |
||
1014 | |||
1015 | return Functions::VALUE(); |
||
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(); |
|
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) |
1056 | { |
||
1057 | 15 | $number = Functions::flattenSingleValue($number); |
|
1058 | |||
1059 | 15 | if (is_numeric($number)) { |
|
1060 | 14 | if ($number < 0) { |
|
1061 | 3 | return Functions::NAN(); |
|
1062 | } |
||
1063 | |||
1064 | 11 | return sqrt($number * M_PI); |
|
1065 | } |
||
1066 | |||
1067 | 1 | return Functions::VALUE(); |
|
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 |
||
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) |
||
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 = []) |
|
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) { |
||
1241 | $aArgs = $aArgsArray[$index]; |
||
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(); |
||
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) |
|
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) |
|
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) |
|
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) |
|
1436 | } |
||
1437 | } |
||
1438 |