PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.0.3
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.0.3
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
visualizer / vendor / phpoffice / phpexcel / Classes / PHPExcel / Calculation / MathTrig.php

MathTrig.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.0.3, at vendor/phpoffice/phpexcel/Classes/PHPExcel/Calculation/MathTrig.php

1,377 lines 37.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * PHPExcel
4 *
5 * Copyright (c) 2006 - 2014 PHPExcel
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * @category PHPExcel
22 * @package PHPExcel_Calculation
23 * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
24 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
25 * @version ##VERSION##, ##DATE##
26 */
27
28
29 /** PHPExcel root directory */
30 if (!defined('PHPEXCEL_ROOT')) {
31 /**
32 * @ignore
33 */
34 define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
35 require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
36 }
37
38
39 /**
40 * PHPExcel_Calculation_MathTrig
41 *
42 * @category PHPExcel
43 * @package PHPExcel_Calculation
44 * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel)
45 */
46 class PHPExcel_Calculation_MathTrig {
47
48 //
49 // Private method to return an array of the factors of the input value
50 //
51 private static function _factors($value) {
52 $startVal = floor(sqrt($value));
53
54 $factorArray = array();
55 for ($i = $startVal; $i > 1; --$i) {
56 if (($value % $i) == 0) {
57 $factorArray = array_merge($factorArray,self::_factors($value / $i));
58 $factorArray = array_merge($factorArray,self::_factors($i));
59 if ($i <= sqrt($value)) {
60 break;
61 }
62 }
63 }
64 if (!empty($factorArray)) {
65 rsort($factorArray);
66 return $factorArray;
67 } else {
68 return array((integer) $value);
69 }
70 } // function _factors()
71
72
73 private static function _romanCut($num, $n) {
74 return ($num - ($num % $n ) ) / $n;
75 } // function _romanCut()
76
77
78 /**
79 * ATAN2
80 *
81 * This function calculates the arc tangent of the two variables x and y. It is similar to
82 * calculating the arc tangent of y ÷ x, except that the signs of both arguments are used
83 * to determine the quadrant of the result.
84 * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a
85 * point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between
86 * -pi and pi, excluding -pi.
87 *
88 * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard
89 * PHP atan2() function, so we need to reverse them here before calling the PHP atan() function.
90 *
91 * Excel Function:
92 * ATAN2(xCoordinate,yCoordinate)
93 *
94 * @access public
95 * @category Mathematical and Trigonometric Functions
96 * @param float $xCoordinate The x-coordinate of the point.
97 * @param float $yCoordinate The y-coordinate of the point.
98 * @return float The inverse tangent of the specified x- and y-coordinates.
99 */
100 public static function ATAN2($xCoordinate = NULL, $yCoordinate = NULL) {
101 $xCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($xCoordinate);
102 $yCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($yCoordinate);
103
104 $xCoordinate = ($xCoordinate !== NULL) ? $xCoordinate : 0.0;
105 $yCoordinate = ($yCoordinate !== NULL) ? $yCoordinate : 0.0;
106
107 if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) &&
108 ((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) {
109 $xCoordinate = (float) $xCoordinate;
110 $yCoordinate = (float) $yCoordinate;
111
112 if (($xCoordinate == 0) && ($yCoordinate == 0)) {
113 return PHPExcel_Calculation_Functions::DIV0();
114 }
115
116 return atan2($yCoordinate, $xCoordinate);
117 }
118 return PHPExcel_Calculation_Functions::VALUE();
119 } // function ATAN2()
120
121
122 /**
123 * CEILING
124 *
125 * Returns number rounded up, away from zero, to the nearest multiple of significance.
126 * For example, if you want to avoid using pennies in your prices and your product is
127 * priced at $4.42, use the formula =CEILING(4.42,0.05) to round prices up to the
128 * nearest nickel.
129 *
130 * Excel Function:
131 * CEILING(number[,significance])
132 *
133 * @access public
134 * @category Mathematical and Trigonometric Functions
135 * @param float $number The number you want to round.
136 * @param float $significance The multiple to which you want to round.
137 * @return float Rounded Number
138 */
139 public static function CEILING($number, $significance = NULL) {
140 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
141 $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance);
142
143 if ((is_null($significance)) &&
144 (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) {
145 $significance = $number/abs($number);
146 }
147
148 if ((is_numeric($number)) && (is_numeric($significance))) {
149 if (($number == 0.0 ) || ($significance == 0.0)) {
150 return 0.0;
151 } elseif (self::SIGN($number) == self::SIGN($significance)) {
152 return ceil($number / $significance) * $significance;
153 } else {
154 return PHPExcel_Calculation_Functions::NaN();
155 }
156 }
157 return PHPExcel_Calculation_Functions::VALUE();
158 } // function CEILING()
159
160
161 /**
162 * COMBIN
163 *
164 * Returns the number of combinations for a given number of items. Use COMBIN to
165 * determine the total possible number of groups for a given number of items.
166 *
167 * Excel Function:
168 * COMBIN(numObjs,numInSet)
169 *
170 * @access public
171 * @category Mathematical and Trigonometric Functions
172 * @param int $numObjs Number of different objects
173 * @param int $numInSet Number of objects in each combination
174 * @return int Number of combinations
175 */
176 public static function COMBIN($numObjs, $numInSet) {
177 $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs);
178 $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet);
179
180 if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
181 if ($numObjs < $numInSet) {
182 return PHPExcel_Calculation_Functions::NaN();
183 } elseif ($numInSet < 0) {
184 return PHPExcel_Calculation_Functions::NaN();
185 }
186 return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
187 }
188 return PHPExcel_Calculation_Functions::VALUE();
189 } // function COMBIN()
190
191
192 /**
193 * EVEN
194 *
195 * Returns number rounded up to the nearest even integer.
196 * You can use this function for processing items that come in twos. For example,
197 * a packing crate accepts rows of one or two items. The crate is full when
198 * the number of items, rounded up to the nearest two, matches the crate's
199 * capacity.
200 *
201 * Excel Function:
202 * EVEN(number)
203 *
204 * @access public
205 * @category Mathematical and Trigonometric Functions
206 * @param float $number Number to round
207 * @return int Rounded Number
208 */
209 public static function EVEN($number) {
210 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
211
212 if (is_null($number)) {
213 return 0;
214 } elseif (is_bool($number)) {
215 $number = (int) $number;
216 }
217
218 if (is_numeric($number)) {
219 $significance = 2 * self::SIGN($number);
220 return (int) self::CEILING($number,$significance);
221 }
222 return PHPExcel_Calculation_Functions::VALUE();
223 } // function EVEN()
224
225
226 /**
227 * FACT
228 *
229 * Returns the factorial of a number.
230 * The factorial of a number is equal to 1*2*3*...* number.
231 *
232 * Excel Function:
233 * FACT(factVal)
234 *
235 * @access public
236 * @category Mathematical and Trigonometric Functions
237 * @param float $factVal Factorial Value
238 * @return int Factorial
239 */
240 public static function FACT($factVal) {
241 $factVal = PHPExcel_Calculation_Functions::flattenSingleValue($factVal);
242
243 if (is_numeric($factVal)) {
244 if ($factVal < 0) {
245 return PHPExcel_Calculation_Functions::NaN();
246 }
247 $factLoop = floor($factVal);
248 if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
249 if ($factVal > $factLoop) {
250 return PHPExcel_Calculation_Functions::NaN();
251 }
252 }
253
254 $factorial = 1;
255 while ($factLoop > 1) {
256 $factorial *= $factLoop--;
257 }
258 return $factorial ;
259 }
260 return PHPExcel_Calculation_Functions::VALUE();
261 } // function FACT()
262
263
264 /**
265 * FACTDOUBLE
266 *
267 * Returns the double factorial of a number.
268 *
269 * Excel Function:
270 * FACTDOUBLE(factVal)
271 *
272 * @access public
273 * @category Mathematical and Trigonometric Functions
274 * @param float $factVal Factorial Value
275 * @return int Double Factorial
276 */
277 public static function FACTDOUBLE($factVal) {
278 $factLoop = PHPExcel_Calculation_Functions::flattenSingleValue($factVal);
279
280 if (is_numeric($factLoop)) {
281 $factLoop = floor($factLoop);
282 if ($factVal < 0) {
283 return PHPExcel_Calculation_Functions::NaN();
284 }
285 $factorial = 1;
286 while ($factLoop > 1) {
287 $factorial *= $factLoop--;
288 --$factLoop;
289 }
290 return $factorial ;
291 }
292 return PHPExcel_Calculation_Functions::VALUE();
293 } // function FACTDOUBLE()
294
295
296 /**
297 * FLOOR
298 *
299 * Rounds number down, toward zero, to the nearest multiple of significance.
300 *
301 * Excel Function:
302 * FLOOR(number[,significance])
303 *
304 * @access public
305 * @category Mathematical and Trigonometric Functions
306 * @param float $number Number to round
307 * @param float $significance Significance
308 * @return float Rounded Number
309 */
310 public static function FLOOR($number, $significance = NULL) {
311 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
312 $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance);
313
314 if ((is_null($significance)) && (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) {
315 $significance = $number/abs($number);
316 }
317
318 if ((is_numeric($number)) && (is_numeric($significance))) {
319 if ($significance == 0.0) {
320 return PHPExcel_Calculation_Functions::DIV0();
321 } elseif ($number == 0.0) {
322 return 0.0;
323 } elseif (self::SIGN($number) == self::SIGN($significance)) {
324 return floor($number / $significance) * $significance;
325 } else {
326 return PHPExcel_Calculation_Functions::NaN();
327 }
328 } else
329
330 return PHPExcel_Calculation_Functions::VALUE();
331 } // function FLOOR()
332
333
334 /**
335 * GCD
336 *
337 * Returns the greatest common divisor of a series of numbers.
338 * The greatest common divisor is the largest integer that divides both
339 * number1 and number2 without a remainder.
340 *
341 * Excel Function:
342 * GCD(number1[,number2[, ...]])
343 *
344 * @access public
345 * @category Mathematical and Trigonometric Functions
346 * @param mixed $arg,... Data values
347 * @return integer Greatest Common Divisor
348 */
349 public static function GCD() {
350 $returnValue = 1;
351 $allValuesFactors = array();
352 // Loop through arguments
353 foreach(PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) {
354 if (!is_numeric($value)) {
355 return PHPExcel_Calculation_Functions::VALUE();
356 } elseif ($value == 0) {
357 continue;
358 } elseif($value < 0) {
359 return PHPExcel_Calculation_Functions::NaN();
360 }
361 $myFactors = self::_factors($value);
362 $myCountedFactors = array_count_values($myFactors);
363 $allValuesFactors[] = $myCountedFactors;
364 }
365 $allValuesCount = count($allValuesFactors);
366 if ($allValuesCount == 0) {
367 return 0;
368 }
369
370 $mergedArray = $allValuesFactors[0];
371 for ($i=1;$i < $allValuesCount; ++$i) {
372 $mergedArray = array_intersect_key($mergedArray,$allValuesFactors[$i]);
373 }
374 $mergedArrayValues = count($mergedArray);
375 if ($mergedArrayValues == 0) {
376 return $returnValue;
377 } elseif ($mergedArrayValues > 1) {
378 foreach($mergedArray as $mergedKey => $mergedValue) {
379 foreach($allValuesFactors as $highestPowerTest) {
380 foreach($highestPowerTest as $testKey => $testValue) {
381 if (($testKey == $mergedKey) && ($testValue < $mergedValue)) {
382 $mergedArray[$mergedKey] = $testValue;
383 $mergedValue = $testValue;
384 }
385 }
386 }
387 }
388
389 $returnValue = 1;
390 foreach($mergedArray as $key => $value) {
391 $returnValue *= pow($key,$value);
392 }
393 return $returnValue;
394 } else {
395 $keys = array_keys($mergedArray);
396 $key = $keys[0];
397 $value = $mergedArray[$key];
398 foreach($allValuesFactors as $testValue) {
399 foreach($testValue as $mergedKey => $mergedValue) {
400 if (($mergedKey == $key) && ($mergedValue < $value)) {
401 $value = $mergedValue;
402 }
403 }
404 }
405 return pow($key,$value);
406 }
407 } // function GCD()
408
409
410 /**
411 * INT
412 *
413 * Casts a floating point value to an integer
414 *
415 * Excel Function:
416 * INT(number)
417 *
418 * @access public
419 * @category Mathematical and Trigonometric Functions
420 * @param float $number Number to cast to an integer
421 * @return integer Integer value
422 */
423 public static function INT($number) {
424 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
425
426 if (is_null($number)) {
427 return 0;
428 } elseif (is_bool($number)) {
429 return (int) $number;
430 }
431 if (is_numeric($number)) {
432 return (int) floor($number);
433 }
434 return PHPExcel_Calculation_Functions::VALUE();
435 } // function INT()
436
437
438 /**
439 * LCM
440 *
441 * Returns the lowest common multiplier of a series of numbers
442 * The least common multiple is the smallest positive integer that is a multiple
443 * of all integer arguments number1, number2, and so on. Use LCM to add fractions
444 * with different denominators.
445 *
446 * Excel Function:
447 * LCM(number1[,number2[, ...]])
448 *
449 * @access public
450 * @category Mathematical and Trigonometric Functions
451 * @param mixed $arg,... Data values
452 * @return int Lowest Common Multiplier
453 */
454 public static function LCM() {
455 $returnValue = 1;
456 $allPoweredFactors = array();
457 // Loop through arguments
458 foreach(PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) {
459 if (!is_numeric($value)) {
460 return PHPExcel_Calculation_Functions::VALUE();
461 }
462 if ($value == 0) {
463 return 0;
464 } elseif ($value < 0) {
465 return PHPExcel_Calculation_Functions::NaN();
466 }
467 $myFactors = self::_factors(floor($value));
468 $myCountedFactors = array_count_values($myFactors);
469 $myPoweredFactors = array();
470 foreach($myCountedFactors as $myCountedFactor => $myCountedPower) {
471 $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor,$myCountedPower);
472 }
473 foreach($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
474 if (array_key_exists($myPoweredValue,$allPoweredFactors)) {
475 if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
476 $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
477 }
478 } else {
479 $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
480 }
481 }
482 }
483 foreach($allPoweredFactors as $allPoweredFactor) {
484 $returnValue *= (integer) $allPoweredFactor;
485 }
486 return $returnValue;
487 } // function LCM()
488
489
490 /**
491 * LOG_BASE
492 *
493 * Returns the logarithm of a number to a specified base. The default base is 10.
494 *
495 * Excel Function:
496 * LOG(number[,base])
497 *
498 * @access public
499 * @category Mathematical and Trigonometric Functions
500 * @param float $number The positive real number for which you want the logarithm
501 * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10.
502 * @return float
503 */
504 public static function LOG_BASE($number = NULL, $base = 10) {
505 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
506 $base = (is_null($base)) ? 10 : (float) PHPExcel_Calculation_Functions::flattenSingleValue($base);
507
508 if ((!is_numeric($base)) || (!is_numeric($number)))
509 return PHPExcel_Calculation_Functions::VALUE();
510 if (($base <= 0) || ($number <= 0))
511 return PHPExcel_Calculation_Functions::NaN();
512 return log($number, $base);
513 } // function LOG_BASE()
514
515
516 /**
517 * MDETERM
518 *
519 * Returns the matrix determinant of an array.
520 *
521 * Excel Function:
522 * MDETERM(array)
523 *
524 * @access public
525 * @category Mathematical and Trigonometric Functions
526 * @param array $matrixValues A matrix of values
527 * @return float
528 */
529 public static function MDETERM($matrixValues) {
530 $matrixData = array();
531 if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); }
532
533 $row = $maxColumn = 0;
534 foreach($matrixValues as $matrixRow) {
535 if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); }
536 $column = 0;
537 foreach($matrixRow as $matrixCell) {
538 if ((is_string($matrixCell)) || ($matrixCell === null)) {
539 return PHPExcel_Calculation_Functions::VALUE();
540 }
541 $matrixData[$column][$row] = $matrixCell;
542 ++$column;
543 }
544 if ($column > $maxColumn) { $maxColumn = $column; }
545 ++$row;
546 }
547 if ($row != $maxColumn) { return PHPExcel_Calculation_Functions::VALUE(); }
548
549 try {
550 $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData);
551 return $matrix->det();
552 } catch (PHPExcel_Exception $ex) {
553 return PHPExcel_Calculation_Functions::VALUE();
554 }
555 } // function MDETERM()
556
557
558 /**
559 * MINVERSE
560 *
561 * Returns the inverse matrix for the matrix stored in an array.
562 *
563 * Excel Function:
564 * MINVERSE(array)
565 *
566 * @access public
567 * @category Mathematical and Trigonometric Functions
568 * @param array $matrixValues A matrix of values
569 * @return array
570 */
571 public static function MINVERSE($matrixValues) {
572 $matrixData = array();
573 if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); }
574
575 $row = $maxColumn = 0;
576 foreach($matrixValues as $matrixRow) {
577 if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); }
578 $column = 0;
579 foreach($matrixRow as $matrixCell) {
580 if ((is_string($matrixCell)) || ($matrixCell === null)) {
581 return PHPExcel_Calculation_Functions::VALUE();
582 }
583 $matrixData[$column][$row] = $matrixCell;
584 ++$column;
585 }
586 if ($column > $maxColumn) { $maxColumn = $column; }
587 ++$row;
588 }
589 if ($row != $maxColumn) { return PHPExcel_Calculation_Functions::VALUE(); }
590
591 try {
592 $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData);
593 return $matrix->inverse()->getArray();
594 } catch (PHPExcel_Exception $ex) {
595 return PHPExcel_Calculation_Functions::VALUE();
596 }
597 } // function MINVERSE()
598
599
600 /**
601 * MMULT
602 *
603 * @param array $matrixData1 A matrix of values
604 * @param array $matrixData2 A matrix of values
605 * @return array
606 */
607 public static function MMULT($matrixData1,$matrixData2) {
608 $matrixAData = $matrixBData = array();
609 if (!is_array($matrixData1)) { $matrixData1 = array(array($matrixData1)); }
610 if (!is_array($matrixData2)) { $matrixData2 = array(array($matrixData2)); }
611
612 try {
613 $rowA = 0;
614 foreach($matrixData1 as $matrixRow) {
615 if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); }
616 $columnA = 0;
617 foreach($matrixRow as $matrixCell) {
618 if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
619 return PHPExcel_Calculation_Functions::VALUE();
620 }
621 $matrixAData[$rowA][$columnA] = $matrixCell;
622 ++$columnA;
623 }
624 ++$rowA;
625 }
626 $matrixA = new PHPExcel_Shared_JAMA_Matrix($matrixAData);
627 $rowB = 0;
628 foreach($matrixData2 as $matrixRow) {
629 if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); }
630 $columnB = 0;
631 foreach($matrixRow as $matrixCell) {
632 if ((!is_numeric($matrixCell)) || ($matrixCell === null)) {
633 return PHPExcel_Calculation_Functions::VALUE();
634 }
635 $matrixBData[$rowB][$columnB] = $matrixCell;
636 ++$columnB;
637 }
638 ++$rowB;
639 }
640 $matrixB = new PHPExcel_Shared_JAMA_Matrix($matrixBData);
641
642 if ($columnA != $rowB) {
643 return PHPExcel_Calculation_Functions::VALUE();
644 }
645
646 return $matrixA->times($matrixB)->getArray();
647 } catch (PHPExcel_Exception $ex) {
648 var_dump($ex->getMessage());
649 return PHPExcel_Calculation_Functions::VALUE();
650 }
651 } // function MMULT()
652
653
654 /**
655 * MOD
656 *
657 * @param int $a Dividend
658 * @param int $b Divisor
659 * @return int Remainder
660 */
661 public static function MOD($a = 1, $b = 1) {
662 $a = PHPExcel_Calculation_Functions::flattenSingleValue($a);
663 $b = PHPExcel_Calculation_Functions::flattenSingleValue($b);
664
665 if ($b == 0.0) {
666 return PHPExcel_Calculation_Functions::DIV0();
667 } elseif (($a < 0.0) && ($b > 0.0)) {
668 return $b - fmod(abs($a),$b);
669 } elseif (($a > 0.0) && ($b < 0.0)) {
670 return $b + fmod($a,abs($b));
671 }
672
673 return fmod($a,$b);
674 } // function MOD()
675
676
677 /**
678 * MROUND
679 *
680 * Rounds a number to the nearest multiple of a specified value
681 *
682 * @param float $number Number to round
683 * @param int $multiple Multiple to which you want to round $number
684 * @return float Rounded Number
685 */
686 public static function MROUND($number,$multiple) {
687 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
688 $multiple = PHPExcel_Calculation_Functions::flattenSingleValue($multiple);
689
690 if ((is_numeric($number)) && (is_numeric($multiple))) {
691 if ($multiple == 0) {
692 return 0;
693 }
694 if ((self::SIGN($number)) == (self::SIGN($multiple))) {
695 $multiplier = 1 / $multiple;
696 return round($number * $multiplier) / $multiplier;
697 }
698 return PHPExcel_Calculation_Functions::NaN();
699 }
700 return PHPExcel_Calculation_Functions::VALUE();
701 } // function MROUND()
702
703
704 /**
705 * MULTINOMIAL
706 *
707 * Returns the ratio of the factorial of a sum of values to the product of factorials.
708 *
709 * @param array of mixed Data Series
710 * @return float
711 */
712 public static function MULTINOMIAL() {
713 $summer = 0;
714 $divisor = 1;
715 // Loop through arguments
716 foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
717 // Is it a numeric value?
718 if (is_numeric($arg)) {
719 if ($arg < 1) {
720 return PHPExcel_Calculation_Functions::NaN();
721 }
722 $summer += floor($arg);
723 $divisor *= self::FACT($arg);
724 } else {
725 return PHPExcel_Calculation_Functions::VALUE();
726 }
727 }
728
729 // Return
730 if ($summer > 0) {
731 $summer = self::FACT($summer);
732 return $summer / $divisor;
733 }
734 return 0;
735 } // function MULTINOMIAL()
736
737
738 /**
739 * ODD
740 *
741 * Returns number rounded up to the nearest odd integer.
742 *
743 * @param float $number Number to round
744 * @return int Rounded Number
745 */
746 public static function ODD($number) {
747 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
748
749 if (is_null($number)) {
750 return 1;
751 } elseif (is_bool($number)) {
752 $number = (int) $number;
753 }
754
755 if (is_numeric($number)) {
756 $significance = self::SIGN($number);
757 if ($significance == 0) {
758 return 1;
759 }
760
761 $result = self::CEILING($number,$significance);
762 if ($result == self::EVEN($result)) {
763 $result += $significance;
764 }
765
766 return (int) $result;
767 }
768 return PHPExcel_Calculation_Functions::VALUE();
769 } // function ODD()
770
771
772 /**
773 * POWER
774 *
775 * Computes x raised to the power y.
776 *
777 * @param float $x
778 * @param float $y
779 * @return float
780 */
781 public static function POWER($x = 0, $y = 2) {
782 $x = PHPExcel_Calculation_Functions::flattenSingleValue($x);
783 $y = PHPExcel_Calculation_Functions::flattenSingleValue($y);
784
785 // Validate parameters
786 if ($x == 0.0 && $y == 0.0) {
787 return PHPExcel_Calculation_Functions::NaN();
788 } elseif ($x == 0.0 && $y < 0.0) {
789 return PHPExcel_Calculation_Functions::DIV0();
790 }
791
792 // Return
793 $result = pow($x, $y);
794 return (!is_nan($result) && !is_infinite($result)) ? $result : PHPExcel_Calculation_Functions::NaN();
795 } // function POWER()
796
797
798 /**
799 * PRODUCT
800 *
801 * PRODUCT returns the product of all the values and cells referenced in the argument list.
802 *
803 * Excel Function:
804 * PRODUCT(value1[,value2[, ...]])
805 *
806 * @access public
807 * @category Mathematical and Trigonometric Functions
808 * @param mixed $arg,... Data values
809 * @return float
810 */
811 public static function PRODUCT() {
812 // Return value
813 $returnValue = null;
814
815 // Loop through arguments
816 foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
817 // Is it a numeric value?
818 if ((is_numeric($arg)) && (!is_string($arg))) {
819 if (is_null($returnValue)) {
820 $returnValue = $arg;
821 } else {
822 $returnValue *= $arg;
823 }
824 }
825 }
826
827 // Return
828 if (is_null($returnValue)) {
829 return 0;
830 }
831 return $returnValue;
832 } // function PRODUCT()
833
834
835 /**
836 * QUOTIENT
837 *
838 * QUOTIENT function returns the integer portion of a division. Numerator is the divided number
839 * and denominator is the divisor.
840 *
841 * Excel Function:
842 * QUOTIENT(value1[,value2[, ...]])
843 *
844 * @access public
845 * @category Mathematical and Trigonometric Functions
846 * @param mixed $arg,... Data values
847 * @return float
848 */
849 public static function QUOTIENT() {
850 // Return value
851 $returnValue = null;
852
853 // Loop through arguments
854 foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
855 // Is it a numeric value?
856 if ((is_numeric($arg)) && (!is_string($arg))) {
857 if (is_null($returnValue)) {
858 $returnValue = ($arg == 0) ? 0 : $arg;
859 } else {
860 if (($returnValue == 0) || ($arg == 0)) {
861 $returnValue = 0;
862 } else {
863 $returnValue /= $arg;
864 }
865 }
866 }
867 }
868
869 // Return
870 return intval($returnValue);
871 } // function QUOTIENT()
872
873
874 /**
875 * RAND
876 *
877 * @param int $min Minimal value
878 * @param int $max Maximal value
879 * @return int Random number
880 */
881 public static function RAND($min = 0, $max = 0) {
882 $min = PHPExcel_Calculation_Functions::flattenSingleValue($min);
883 $max = PHPExcel_Calculation_Functions::flattenSingleValue($max);
884
885 if ($min == 0 && $max == 0) {
886 return (mt_rand(0,10000000)) / 10000000;
887 } else {
888 return mt_rand($min, $max);
889 }
890 } // function RAND()
891
892
893 public static function ROMAN($aValue, $style=0) {
894 $aValue = PHPExcel_Calculation_Functions::flattenSingleValue($aValue);
895 $style = (is_null($style)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($style);
896 if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) {
897 return PHPExcel_Calculation_Functions::VALUE();
898 }
899 $aValue = (integer) $aValue;
900 if ($aValue == 0) {
901 return '';
902 }
903
904 $mill = Array('', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM');
905 $cent = Array('', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM');
906 $tens = Array('', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC');
907 $ones = Array('', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX');
908
909 $roman = '';
910 while ($aValue > 5999) {
911 $roman .= 'M';
912 $aValue -= 1000;
913 }
914 $m = self::_romanCut($aValue, 1000); $aValue %= 1000;
915 $c = self::_romanCut($aValue, 100); $aValue %= 100;
916 $t = self::_romanCut($aValue, 10); $aValue %= 10;
917
918 return $roman.$mill[$m].$cent[$c].$tens[$t].$ones[$aValue];
919 } // function ROMAN()
920
921
922 /**
923 * ROUNDUP
924 *
925 * Rounds a number up to a specified number of decimal places
926 *
927 * @param float $number Number to round
928 * @param int $digits Number of digits to which you want to round $number
929 * @return float Rounded Number
930 */
931 public static function ROUNDUP($number,$digits) {
932 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
933 $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
934
935 if ((is_numeric($number)) && (is_numeric($digits))) {
936 $significance = pow(10,(int) $digits);
937 if ($number < 0.0) {
938 return floor($number * $significance) / $significance;
939 } else {
940 return ceil($number * $significance) / $significance;
941 }
942 }
943 return PHPExcel_Calculation_Functions::VALUE();
944 } // function ROUNDUP()
945
946
947 /**
948 * ROUNDDOWN
949 *
950 * Rounds a number down to a specified number of decimal places
951 *
952 * @param float $number Number to round
953 * @param int $digits Number of digits to which you want to round $number
954 * @return float Rounded Number
955 */
956 public static function ROUNDDOWN($number,$digits) {
957 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
958 $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
959
960 if ((is_numeric($number)) && (is_numeric($digits))) {
961 $significance = pow(10,(int) $digits);
962 if ($number < 0.0) {
963 return ceil($number * $significance) / $significance;
964 } else {
965 return floor($number * $significance) / $significance;
966 }
967 }
968 return PHPExcel_Calculation_Functions::VALUE();
969 } // function ROUNDDOWN()
970
971
972 /**
973 * SERIESSUM
974 *
975 * Returns the sum of a power series
976 *
977 * @param float $x Input value to the power series
978 * @param float $n Initial power to which you want to raise $x
979 * @param float $m Step by which to increase $n for each term in the series
980 * @param array of mixed Data Series
981 * @return float
982 */
983 public static function SERIESSUM() {
984 // Return value
985 $returnValue = 0;
986
987 // Loop through arguments
988 $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
989
990 $x = array_shift($aArgs);
991 $n = array_shift($aArgs);
992 $m = array_shift($aArgs);
993
994 if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
995 // Calculate
996 $i = 0;
997 foreach($aArgs as $arg) {
998 // Is it a numeric value?
999 if ((is_numeric($arg)) && (!is_string($arg))) {
1000 $returnValue += $arg * pow($x,$n + ($m * $i++));
1001 } else {
1002 return PHPExcel_Calculation_Functions::VALUE();
1003 }
1004 }
1005 // Return
1006 return $returnValue;
1007 }
1008 return PHPExcel_Calculation_Functions::VALUE();
1009 } // function SERIESSUM()
1010
1011
1012 /**
1013 * SIGN
1014 *
1015 * Determines the sign of a number. Returns 1 if the number is positive, zero (0)
1016 * if the number is 0, and -1 if the number is negative.
1017 *
1018 * @param float $number Number to round
1019 * @return int sign value
1020 */
1021 public static function SIGN($number) {
1022 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
1023
1024 if (is_bool($number))
1025 return (int) $number;
1026 if (is_numeric($number)) {
1027 if ($number == 0.0) {
1028 return 0;
1029 }
1030 return $number / abs($number);
1031 }
1032 return PHPExcel_Calculation_Functions::VALUE();
1033 } // function SIGN()
1034
1035
1036 /**
1037 * SQRTPI
1038 *
1039 * Returns the square root of (number * pi).
1040 *
1041 * @param float $number Number
1042 * @return float Square Root of Number * Pi
1043 */
1044 public static function SQRTPI($number) {
1045 $number = PHPExcel_Calculation_Functions::flattenSingleValue($number);
1046
1047 if (is_numeric($number)) {
1048 if ($number < 0) {
1049 return PHPExcel_Calculation_Functions::NaN();
1050 }
1051 return sqrt($number * M_PI) ;
1052 }
1053 return PHPExcel_Calculation_Functions::VALUE();
1054 } // function SQRTPI()
1055
1056
1057 /**
1058 * SUBTOTAL
1059 *
1060 * Returns a subtotal in a list or database.
1061 *
1062 * @param int the number 1 to 11 that specifies which function to
1063 * use in calculating subtotals within a list.
1064 * @param array of mixed Data Series
1065 * @return float
1066 */
1067 public static function SUBTOTAL() {
1068 $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
1069
1070 // Calculate
1071 $subtotal = array_shift($aArgs);
1072
1073 if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
1074 switch($subtotal) {
1075 case 1 :
1076 return PHPExcel_Calculation_Statistical::AVERAGE($aArgs);
1077 break;
1078 case 2 :
1079 return PHPExcel_Calculation_Statistical::COUNT($aArgs);
1080 break;
1081 case 3 :
1082 return PHPExcel_Calculation_Statistical::COUNTA($aArgs);
1083 break;
1084 case 4 :
1085 return PHPExcel_Calculation_Statistical::MAX($aArgs);
1086 break;
1087 case 5 :
1088 return PHPExcel_Calculation_Statistical::MIN($aArgs);
1089 break;
1090 case 6 :
1091 return self::PRODUCT($aArgs);
1092 break;
1093 case 7 :
1094 return PHPExcel_Calculation_Statistical::STDEV($aArgs);
1095 break;
1096 case 8 :
1097 return PHPExcel_Calculation_Statistical::STDEVP($aArgs);
1098 break;
1099 case 9 :
1100 return self::SUM($aArgs);
1101 break;
1102 case 10 :
1103 return PHPExcel_Calculation_Statistical::VARFunc($aArgs);
1104 break;
1105 case 11 :
1106 return PHPExcel_Calculation_Statistical::VARP($aArgs);
1107 break;
1108 }
1109 }
1110 return PHPExcel_Calculation_Functions::VALUE();
1111 } // function SUBTOTAL()
1112
1113
1114 /**
1115 * SUM
1116 *
1117 * SUM computes the sum of all the values and cells referenced in the argument list.
1118 *
1119 * Excel Function:
1120 * SUM(value1[,value2[, ...]])
1121 *
1122 * @access public
1123 * @category Mathematical and Trigonometric Functions
1124 * @param mixed $arg,... Data values
1125 * @return float
1126 */
1127 public static function SUM() {
1128 // Return value
1129 $returnValue = 0;
1130
1131 // Loop through the arguments
1132 foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
1133 // Is it a numeric value?
1134 if ((is_numeric($arg)) && (!is_string($arg))) {
1135 $returnValue += $arg;
1136 }
1137 }
1138
1139 // Return
1140 return $returnValue;
1141 } // function SUM()
1142
1143
1144 /**
1145 * SUMIF
1146 *
1147 * Counts the number of cells that contain numbers within the list of arguments
1148 *
1149 * Excel Function:
1150 * SUMIF(value1[,value2[, ...]],condition)
1151 *
1152 * @access public
1153 * @category Mathematical and Trigonometric Functions
1154 * @param mixed $arg,... Data values
1155 * @param string $condition The criteria that defines which cells will be summed.
1156 * @return float
1157 */
1158 public static function SUMIF($aArgs,$condition,$sumArgs = array()) {
1159 // Return value
1160 $returnValue = 0;
1161
1162 $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
1163 $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
1164 if (empty($sumArgs)) {
1165 $sumArgs = $aArgs;
1166 }
1167 $condition = PHPExcel_Calculation_Functions::_ifCondition($condition);
1168 // Loop through arguments
1169 foreach ($aArgs as $key => $arg) {
1170 if (!is_numeric($arg)) {
1171 $arg = str_replace('"', '""', $arg);
1172 $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg));
1173 }
1174
1175 $testCondition = '='.$arg.$condition;
1176 if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
1177 // Is it a value within our criteria
1178 $returnValue += $sumArgs[$key];
1179 }
1180 }
1181
1182 // Return
1183 return $returnValue;
1184 } // function SUMIF()
1185
1186
1187 /**
1188 * SUMPRODUCT
1189 *
1190 * Excel Function:
1191 * SUMPRODUCT(value1[,value2[, ...]])
1192 *
1193 * @access public
1194 * @category Mathematical and Trigonometric Functions
1195 * @param mixed $arg,... Data values
1196 * @return float
1197 */
1198 public static function SUMPRODUCT() {
1199 $arrayList = func_get_args();
1200
1201 $wrkArray = PHPExcel_Calculation_Functions::flattenArray(array_shift($arrayList));
1202 $wrkCellCount = count($wrkArray);
1203
1204 for ($i=0; $i< $wrkCellCount; ++$i) {
1205 if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) {
1206 $wrkArray[$i] = 0;
1207 }
1208 }
1209
1210 foreach($arrayList as $matrixData) {
1211 $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData);
1212 $count = count($array2);
1213 if ($wrkCellCount != $count) {
1214 return PHPExcel_Calculation_Functions::VALUE();
1215 }
1216
1217 foreach ($array2 as $i => $val) {
1218 if ((!is_numeric($val)) || (is_string($val))) {
1219 $val = 0;
1220 }
1221 $wrkArray[$i] *= $val;
1222 }
1223 }
1224
1225 return array_sum($wrkArray);
1226 } // function SUMPRODUCT()
1227
1228
1229 /**
1230 * SUMSQ
1231 *
1232 * SUMSQ returns the sum of the squares of the arguments
1233 *
1234 * Excel Function:
1235 * SUMSQ(value1[,value2[, ...]])
1236 *
1237 * @access public
1238 * @category Mathematical and Trigonometric Functions
1239 * @param mixed $arg,... Data values
1240 * @return float
1241 */
1242 public static function SUMSQ() {
1243 // Return value
1244 $returnValue = 0;
1245
1246 // Loop through arguments
1247 foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) {
1248 // Is it a numeric value?
1249 if ((is_numeric($arg)) && (!is_string($arg))) {
1250 $returnValue += ($arg * $arg);
1251 }
1252 }
1253
1254 // Return
1255 return $returnValue;
1256 } // function SUMSQ()
1257
1258
1259 /**
1260 * SUMX2MY2
1261 *
1262 * @param mixed[] $matrixData1 Matrix #1
1263 * @param mixed[] $matrixData2 Matrix #2
1264 * @return float
1265 */
1266 public static function SUMX2MY2($matrixData1,$matrixData2) {
1267 $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
1268 $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
1269 $count1 = count($array1);
1270 $count2 = count($array2);
1271 if ($count1 < $count2) {
1272 $count = $count1;
1273 } else {
1274 $count = $count2;
1275 }
1276
1277 $result = 0;
1278 for ($i = 0; $i < $count; ++$i) {
1279 if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1280 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1281 $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]);
1282 }
1283 }
1284
1285 return $result;
1286 } // function SUMX2MY2()
1287
1288
1289 /**
1290 * SUMX2PY2
1291 *
1292 * @param mixed[] $matrixData1 Matrix #1
1293 * @param mixed[] $matrixData2 Matrix #2
1294 * @return float
1295 */
1296 public static function SUMX2PY2($matrixData1,$matrixData2) {
1297 $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
1298 $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
1299 $count1 = count($array1);
1300 $count2 = count($array2);
1301 if ($count1 < $count2) {
1302 $count = $count1;
1303 } else {
1304 $count = $count2;
1305 }
1306
1307 $result = 0;
1308 for ($i = 0; $i < $count; ++$i) {
1309 if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1310 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1311 $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]);
1312 }
1313 }
1314
1315 return $result;
1316 } // function SUMX2PY2()
1317
1318
1319 /**
1320 * SUMXMY2
1321 *
1322 * @param mixed[] $matrixData1 Matrix #1
1323 * @param mixed[] $matrixData2 Matrix #2
1324 * @return float
1325 */
1326 public static function SUMXMY2($matrixData1,$matrixData2) {
1327 $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1);
1328 $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2);
1329 $count1 = count($array1);
1330 $count2 = count($array2);
1331 if ($count1 < $count2) {
1332 $count = $count1;
1333 } else {
1334 $count = $count2;
1335 }
1336
1337 $result = 0;
1338 for ($i = 0; $i < $count; ++$i) {
1339 if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) &&
1340 ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) {
1341 $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]);
1342 }
1343 }
1344
1345 return $result;
1346 } // function SUMXMY2()
1347
1348
1349 /**
1350 * TRUNC
1351 *
1352 * Truncates value to the number of fractional digits by number_digits.
1353 *
1354 * @param float $value
1355 * @param int $digits
1356 * @return float Truncated value
1357 */
1358 public static function TRUNC($value = 0, $digits = 0) {
1359 $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
1360 $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits);
1361
1362 // Validate parameters
1363 if ((!is_numeric($value)) || (!is_numeric($digits)))
1364 return PHPExcel_Calculation_Functions::VALUE();
1365 $digits = floor($digits);
1366
1367 // Truncate
1368 $adjust = pow(10, $digits);
1369
1370 if (($digits > 0) && (rtrim(intval((abs($value) - abs(intval($value))) * $adjust),'0') < $adjust/10))
1371 return $value;
1372
1373 return (intval($value * $adjust)) / $adjust;
1374 } // function TRUNC()
1375
1376 } // class PHPExcel_Calculation_MathTrig
1377