PageRenderTime 67ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 1ms

/common/libraries/plugin/phpexcel/PHPExcel/Calculation/MathTrig.php

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