PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/framework/lib/classes/PHPExcel/Calculation/MathTrig.php

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