PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/include/PHPExcel/Calculation/MathTrig.php

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