PageRenderTime 61ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 1ms

/branches/v1.6.5/Classes/PHPExcel/Calculation/Functions.php

#
PHP | 7142 lines | 4199 code | 675 blank | 2268 comment | 1299 complexity | 78eaacab02c64a14509049ef66dcdc67 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.0, LGPL-2.1, GPL-3.0, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2009 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 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version ##VERSION##, ##DATE##
  26. */
  27. define('EPS', 2.22e-16);
  28. define('MAX_VALUE', 1.2e308);
  29. define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
  30. define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
  31. define('XMININ', 2.23e-308);
  32. define('MAX_ITERATIONS', 150);
  33. define('PRECISION', 8.88E-016);
  34. define('EULER', 2.71828182845904523536);
  35. $savedPrecision = ini_get('precision');
  36. if ($savedPrecision < 15) {
  37. ini_set('precision',15);
  38. }
  39. /** PHPExcel_Cell */
  40. require_once 'PHPExcel/Cell.php';
  41. /** PHPExcel_Cell_DataType */
  42. require_once 'PHPExcel/Cell/DataType.php';
  43. /** PHPExcel_Shared_Date */
  44. require_once 'PHPExcel/Shared/Date.php';
  45. /** PHPExcel_Shared_Date */
  46. require_once 'PHPExcel/Shared/JAMA/Matrix.php';
  47. /**
  48. * PHPExcel_Calculation_Functions
  49. *
  50. * @category PHPExcel
  51. * @package PHPExcel_Calculation
  52. * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
  53. */
  54. class PHPExcel_Calculation_Functions {
  55. /** constants */
  56. const COMPATIBILITY_EXCEL = 'Excel';
  57. const COMPATIBILITY_GNUMERIC = 'Gnumeric';
  58. const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc';
  59. const RETURNDATE_PHP_NUMERIC = 'P';
  60. const RETURNDATE_PHP_OBJECT = 'O';
  61. const RETURNDATE_EXCEL = 'E';
  62. /**
  63. * Compatibility mode to use for error checking and responses
  64. *
  65. * @var string
  66. */
  67. private static $compatibilityMode = self::COMPATIBILITY_EXCEL;
  68. /**
  69. * Data Type to use when returning date values
  70. *
  71. * @var integer
  72. */
  73. private static $ReturnDateType = self::RETURNDATE_PHP_NUMERIC;
  74. /**
  75. * List of error codes
  76. *
  77. * @var array
  78. */
  79. private static $_errorCodes = array( 'null' => '#NULL!',
  80. 'divisionbyzero' => '#DIV/0!',
  81. 'value' => '#VALUE!',
  82. 'reference' => '#REF!',
  83. 'name' => '#NAME?',
  84. 'num' => '#NUM!',
  85. 'na' => '#N/A',
  86. 'gettingdata' => '#GETTING_DATA'
  87. );
  88. /**
  89. * Set the Compatibility Mode
  90. *
  91. * @param string $compatibilityMode Compatibility Mode
  92. * @return boolean (Success or Failure)
  93. */
  94. public static function setCompatibilityMode($compatibilityMode) {
  95. if (($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
  96. ($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
  97. ($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  98. self::$compatibilityMode = $compatibilityMode;
  99. return True;
  100. }
  101. return False;
  102. }
  103. /**
  104. * Return the current Compatibility Mode
  105. *
  106. * @return string $compatibilityMode Compatibility Mode
  107. */
  108. public static function getCompatibilityMode() {
  109. return self::$compatibilityMode;
  110. }
  111. /**
  112. * Set the Return Date Format (Excel, PHP Serialized or PHP Object)
  113. *
  114. * @param integer $returnDateType Return Date Format
  115. * @return boolean Success or failure
  116. */
  117. public static function setReturnDateType($returnDateType) {
  118. if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) ||
  119. ($returnDateType == self::RETURNDATE_PHP_OBJECT) ||
  120. ($returnDateType == self::RETURNDATE_EXCEL)) {
  121. self::$ReturnDateType = $returnDateType;
  122. return True;
  123. }
  124. return False;
  125. } // function setReturnDateType()
  126. /**
  127. * Return the Return Date Format (Excel, PHP Serialized or PHP Object)
  128. *
  129. * @return integer $returnDateType Return Date Format
  130. */
  131. public static function getReturnDateType() {
  132. return self::$ReturnDateType;
  133. } // function getReturnDateType()
  134. /**
  135. * DUMMY
  136. *
  137. * @return string #NAME?
  138. */
  139. public static function DUMMY() {
  140. return self::$_errorCodes['name'];
  141. }
  142. /**
  143. * NA
  144. *
  145. * @return string #N/A!
  146. */
  147. public static function NA() {
  148. return self::$_errorCodes['na'];
  149. }
  150. /**
  151. * LOGICAL_AND
  152. *
  153. * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE.
  154. *
  155. * Booleans arguments are treated as True or False as appropriate
  156. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  157. * If any argument value is a string, or a Null, it is ignored
  158. *
  159. * Quirk of Excel:
  160. * String values passed directly to the function rather than through a cell reference
  161. * e.g.=AND(1,"A",1)
  162. * will return a #VALUE! error, _not_ ignoring the string.
  163. * This behaviour is not replicated
  164. *
  165. * @param array of mixed Data Series
  166. * @return boolean
  167. */
  168. public static function LOGICAL_AND() {
  169. // Return value
  170. $returnValue = True;
  171. // Loop through the arguments
  172. $aArgs = self::flattenArray(func_get_args());
  173. $argCount = 0;
  174. foreach ($aArgs as $arg) {
  175. // Is it a boolean value?
  176. if (is_bool($arg)) {
  177. $returnValue = $returnValue && $arg;
  178. ++$argCount;
  179. } elseif ((is_numeric($arg)) && (!is_string($arg))) {
  180. $returnValue = $returnValue && ($arg != 0);
  181. ++$argCount;
  182. }
  183. }
  184. // Return
  185. if ($argCount == 0) {
  186. return self::$_errorCodes['value'];
  187. }
  188. return $returnValue;
  189. }
  190. /**
  191. * LOGICAL_OR
  192. *
  193. * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE.
  194. *
  195. * Booleans arguments are treated as True or False as appropriate
  196. * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
  197. * If any argument value is a string, or a Null, it is ignored
  198. *
  199. * @param array of mixed Data Series
  200. * @return boolean
  201. */
  202. public static function LOGICAL_OR() {
  203. // Return value
  204. $returnValue = False;
  205. // Loop through the arguments
  206. $aArgs = self::flattenArray(func_get_args());
  207. $argCount = 0;
  208. foreach ($aArgs as $arg) {
  209. // Is it a boolean value?
  210. if (is_bool($arg)) {
  211. $returnValue = $returnValue || $arg;
  212. ++$argCount;
  213. } elseif ((is_numeric($arg)) && (!is_string($arg))) {
  214. $returnValue = $returnValue || ($arg != 0);
  215. ++$argCount;
  216. }
  217. }
  218. // Return
  219. if ($argCount == 0) {
  220. return self::$_errorCodes['value'];
  221. }
  222. return $returnValue;
  223. }
  224. /**
  225. * LOGICAL_FALSE
  226. *
  227. * Returns FALSE.
  228. *
  229. * @return boolean
  230. */
  231. public static function LOGICAL_FALSE() {
  232. return False;
  233. }
  234. /**
  235. * LOGICAL_TRUE
  236. *
  237. * Returns TRUE.
  238. *
  239. * @return boolean
  240. */
  241. public static function LOGICAL_TRUE() {
  242. return True;
  243. }
  244. /**
  245. * ATAN2
  246. *
  247. * This function calculates the arc tangent of the two variables x and y. It is similar to
  248. * calculating the arc tangent of y / x, except that the signs of both arguments are used
  249. * to determine the quadrant of the result.
  250. * Note that Excel reverses the arguments, so we need to reverse them here before calling the
  251. * standard PHP atan() function
  252. *
  253. * @param float $x Number
  254. * @param float $y Number
  255. * @return float Square Root of Number * Pi
  256. */
  257. public static function REVERSE_ATAN2($x, $y) {
  258. $x = self::flattenSingleValue($x);
  259. $y = self::flattenSingleValue($y);
  260. return atan2($y, $x);
  261. }
  262. /**
  263. * SUM
  264. *
  265. * SUM computes the sum of all the values and cells referenced in the argument list.
  266. *
  267. * @param array of mixed Data Series
  268. * @return float
  269. */
  270. public static function SUM() {
  271. // Return value
  272. $returnValue = 0;
  273. // Loop through the arguments
  274. $aArgs = self::flattenArray(func_get_args());
  275. foreach ($aArgs as $arg) {
  276. // Is it a numeric value?
  277. if ((is_numeric($arg)) && (!is_string($arg))) {
  278. $returnValue += $arg;
  279. }
  280. }
  281. // Return
  282. return $returnValue;
  283. }
  284. /**
  285. * SUMSQ
  286. *
  287. * Returns the sum of the squares of the arguments
  288. *
  289. * @param array of mixed Data Series
  290. * @return float
  291. */
  292. public static function SUMSQ() {
  293. // Return value
  294. $returnValue = 0;
  295. // Loop trough arguments
  296. $aArgs = self::flattenArray(func_get_args());
  297. foreach ($aArgs as $arg) {
  298. // Is it a numeric value?
  299. if ((is_numeric($arg)) && (!is_string($arg))) {
  300. $returnValue += pow($arg,2);
  301. }
  302. }
  303. // Return
  304. return $returnValue;
  305. }
  306. /**
  307. * PRODUCT
  308. *
  309. * PRODUCT returns the product of all the values and cells referenced in the argument list.
  310. *
  311. * @param array of mixed Data Series
  312. * @return float
  313. */
  314. public static function PRODUCT() {
  315. // Return value
  316. $returnValue = null;
  317. // Loop trough arguments
  318. $aArgs = self::flattenArray(func_get_args());
  319. foreach ($aArgs as $arg) {
  320. // Is it a numeric value?
  321. if ((is_numeric($arg)) && (!is_string($arg))) {
  322. if (is_null($returnValue)) {
  323. $returnValue = $arg;
  324. } else {
  325. $returnValue *= $arg;
  326. }
  327. }
  328. }
  329. // Return
  330. if (is_null($returnValue)) {
  331. return 0;
  332. }
  333. return $returnValue;
  334. }
  335. /**
  336. * QUOTIENT
  337. *
  338. * QUOTIENT function returns the integer portion of a division.numerator is the divided number
  339. * and denominator is the divisor.
  340. *
  341. * @param array of mixed Data Series
  342. * @return float
  343. */
  344. public static function QUOTIENT() {
  345. // Return value
  346. $returnValue = null;
  347. // Loop trough arguments
  348. $aArgs = self::flattenArray(func_get_args());
  349. foreach ($aArgs as $arg) {
  350. // Is it a numeric value?
  351. if ((is_numeric($arg)) && (!is_string($arg))) {
  352. if (is_null($returnValue)) {
  353. if (($returnValue == 0) || ($arg == 0)) {
  354. $returnValue = 0;
  355. } else {
  356. $returnValue = $arg;
  357. }
  358. } else {
  359. if (($returnValue == 0) || ($arg == 0)) {
  360. $returnValue = 0;
  361. } else {
  362. $returnValue /= $arg;
  363. }
  364. }
  365. }
  366. }
  367. // Return
  368. return intval($returnValue);
  369. }
  370. /**
  371. * MIN
  372. *
  373. * MIN returns the value of the element of the values passed that has the smallest value,
  374. * with negative numbers considered smaller than positive numbers.
  375. *
  376. * @param array of mixed Data Series
  377. * @return float
  378. */
  379. public static function MIN() {
  380. // Return value
  381. $returnValue = null;
  382. // Loop trough arguments
  383. $aArgs = self::flattenArray(func_get_args());
  384. foreach ($aArgs as $arg) {
  385. // Is it a numeric value?
  386. if ((is_numeric($arg)) && (!is_string($arg))) {
  387. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  388. $returnValue = $arg;
  389. }
  390. }
  391. }
  392. // Return
  393. if(is_null($returnValue)) {
  394. return 0;
  395. }
  396. return $returnValue;
  397. }
  398. /**
  399. * MINA
  400. *
  401. * Returns the smallest value in a list of arguments, including numbers, text, and logical values
  402. *
  403. * @param array of mixed Data Series
  404. * @return float
  405. */
  406. public static function MINA() {
  407. // Return value
  408. $returnValue = null;
  409. // Loop through arguments
  410. $aArgs = self::flattenArray(func_get_args());
  411. foreach ($aArgs as $arg) {
  412. // Is it a numeric value?
  413. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  414. if (is_bool($arg)) {
  415. $arg = (integer) $arg;
  416. } elseif (is_string($arg)) {
  417. $arg = 0;
  418. }
  419. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  420. $returnValue = $arg;
  421. }
  422. }
  423. }
  424. // Return
  425. if(is_null($returnValue)) {
  426. return 0;
  427. }
  428. return $returnValue;
  429. }
  430. /**
  431. * SMALL
  432. *
  433. * Returns the nth smallest value in a data set. You can use this function to
  434. * select a value based on its relative standing.
  435. *
  436. * @param array of mixed Data Series
  437. * @param float Entry in the series to return
  438. * @return float
  439. */
  440. public static function SMALL() {
  441. $aArgs = self::flattenArray(func_get_args());
  442. // Calculate
  443. $n = array_pop($aArgs);
  444. if ((is_numeric($n)) && (!is_string($n))) {
  445. $mArgs = array();
  446. foreach ($aArgs as $arg) {
  447. // Is it a numeric value?
  448. if ((is_numeric($arg)) && (!is_string($arg))) {
  449. $mArgs[] = $arg;
  450. }
  451. }
  452. $count = self::COUNT($mArgs);
  453. $n = floor(--$n);
  454. if (($n < 0) || ($n >= $count) || ($count == 0)) {
  455. return self::$_errorCodes['num'];
  456. }
  457. sort($mArgs);
  458. return $mArgs[$n];
  459. }
  460. return self::$_errorCodes['value'];
  461. }
  462. /**
  463. * MAX
  464. *
  465. * MAX returns the value of the element of the values passed that has the highest value,
  466. * with negative numbers considered smaller than positive numbers.
  467. *
  468. * @param array of mixed Data Series
  469. * @return float
  470. */
  471. public static function MAX() {
  472. // Return value
  473. $returnValue = null;
  474. // Loop trough arguments
  475. $aArgs = self::flattenArray(func_get_args());
  476. foreach ($aArgs as $arg) {
  477. // Is it a numeric value?
  478. if ((is_numeric($arg)) && (!is_string($arg))) {
  479. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  480. $returnValue = $arg;
  481. }
  482. }
  483. }
  484. // Return
  485. if(is_null($returnValue)) {
  486. return 0;
  487. }
  488. return $returnValue;
  489. }
  490. /**
  491. * MAXA
  492. *
  493. * Returns the greatest value in a list of arguments, including numbers, text, and logical values
  494. *
  495. * @param array of mixed Data Series
  496. * @return float
  497. */
  498. public static function MAXA() {
  499. // Return value
  500. $returnValue = null;
  501. // Loop through arguments
  502. $aArgs = self::flattenArray(func_get_args());
  503. foreach ($aArgs as $arg) {
  504. // Is it a numeric value?
  505. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  506. if (is_bool($arg)) {
  507. $arg = (integer) $arg;
  508. } elseif (is_string($arg)) {
  509. $arg = 0;
  510. }
  511. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  512. $returnValue = $arg;
  513. }
  514. }
  515. }
  516. // Return
  517. if(is_null($returnValue)) {
  518. return 0;
  519. }
  520. return $returnValue;
  521. }
  522. /**
  523. * LARGE
  524. *
  525. * Returns the nth largest value in a data set. You can use this function to
  526. * select a value based on its relative standing.
  527. *
  528. * @param array of mixed Data Series
  529. * @param float Entry in the series to return
  530. * @return float
  531. *
  532. */
  533. public static function LARGE() {
  534. $aArgs = self::flattenArray(func_get_args());
  535. // Calculate
  536. $n = floor(array_pop($aArgs));
  537. if ((is_numeric($n)) && (!is_string($n))) {
  538. $mArgs = array();
  539. foreach ($aArgs as $arg) {
  540. // Is it a numeric value?
  541. if ((is_numeric($arg)) && (!is_string($arg))) {
  542. $mArgs[] = $arg;
  543. }
  544. }
  545. $count = self::COUNT($mArgs);
  546. $n = floor(--$n);
  547. if (($n < 0) || ($n >= $count) || ($count == 0)) {
  548. return self::$_errorCodes['num'];
  549. }
  550. rsort($mArgs);
  551. return $mArgs[$n];
  552. }
  553. return self::$_errorCodes['value'];
  554. }
  555. /**
  556. * PERCENTILE
  557. *
  558. * Returns the nth percentile of values in a range..
  559. *
  560. * @param array of mixed Data Series
  561. * @param float $entry Entry in the series to return
  562. * @return float
  563. */
  564. public static function PERCENTILE() {
  565. $aArgs = self::flattenArray(func_get_args());
  566. // Calculate
  567. $entry = array_pop($aArgs);
  568. if ((is_numeric($entry)) && (!is_string($entry))) {
  569. if (($entry < 0) || ($entry > 1)) {
  570. return self::$_errorCodes['num'];
  571. }
  572. $mArgs = array();
  573. foreach ($aArgs as $arg) {
  574. // Is it a numeric value?
  575. if ((is_numeric($arg)) && (!is_string($arg))) {
  576. $mArgs[] = $arg;
  577. }
  578. }
  579. $mValueCount = count($mArgs);
  580. if ($mValueCount > 0) {
  581. sort($mArgs);
  582. $count = self::COUNT($mArgs);
  583. $index = $entry * ($count-1);
  584. $iBase = floor($index);
  585. if ($index == $iBase) {
  586. return $mArgs[$index];
  587. } else {
  588. $iNext = $iBase + 1;
  589. $iProportion = $index - $iBase;
  590. return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
  591. }
  592. }
  593. }
  594. return self::$_errorCodes['value'];
  595. }
  596. /**
  597. * QUARTILE
  598. *
  599. * Returns the quartile of a data set.
  600. *
  601. * @param array of mixed Data Series
  602. * @param float $entry Entry in the series to return
  603. * @return float
  604. */
  605. public static function QUARTILE() {
  606. $aArgs = self::flattenArray(func_get_args());
  607. // Calculate
  608. $entry = floor(array_pop($aArgs));
  609. if ((is_numeric($entry)) && (!is_string($entry))) {
  610. $entry /= 4;
  611. if (($entry < 0) || ($entry > 1)) {
  612. return self::$_errorCodes['num'];
  613. }
  614. return self::PERCENTILE($aArgs,$entry);
  615. }
  616. return self::$_errorCodes['value'];
  617. }
  618. /**
  619. * COUNT
  620. *
  621. * Counts the number of cells that contain numbers within the list of arguments
  622. *
  623. * @param array of mixed Data Series
  624. * @return int
  625. */
  626. public static function COUNT() {
  627. // Return value
  628. $returnValue = 0;
  629. // Loop trough arguments
  630. $aArgs = self::flattenArray(func_get_args());
  631. foreach ($aArgs as $arg) {
  632. if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  633. $arg = (int) $arg;
  634. }
  635. // Is it a numeric value?
  636. if ((is_numeric($arg)) && (!is_string($arg))) {
  637. ++$returnValue;
  638. }
  639. }
  640. // Return
  641. return $returnValue;
  642. }
  643. /**
  644. * COUNTBLANK
  645. *
  646. * Counts the number of empty cells within the list of arguments
  647. *
  648. * @param array of mixed Data Series
  649. * @return int
  650. */
  651. public static function COUNTBLANK() {
  652. // Return value
  653. $returnValue = 0;
  654. // Loop trough arguments
  655. $aArgs = self::flattenArray(func_get_args());
  656. foreach ($aArgs as $arg) {
  657. // Is it a blank cell?
  658. if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
  659. ++$returnValue;
  660. }
  661. }
  662. // Return
  663. return $returnValue;
  664. }
  665. /**
  666. * COUNTA
  667. *
  668. * Counts the number of cells that are not empty within the list of arguments
  669. *
  670. * @param array of mixed Data Series
  671. * @return int
  672. */
  673. public static function COUNTA() {
  674. // Return value
  675. $returnValue = 0;
  676. // Loop through arguments
  677. $aArgs = self::flattenArray(func_get_args());
  678. foreach ($aArgs as $arg) {
  679. // Is it a numeric, boolean or string value?
  680. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  681. ++$returnValue;
  682. }
  683. }
  684. // Return
  685. return $returnValue;
  686. }
  687. /**
  688. * AVERAGE
  689. *
  690. * Returns the average (arithmetic mean) of the arguments
  691. *
  692. * @param array of mixed Data Series
  693. * @return float
  694. */
  695. public static function AVERAGE() {
  696. // Return value
  697. $returnValue = 0;
  698. // Loop through arguments
  699. $aArgs = self::flattenArray(func_get_args());
  700. $aCount = 0;
  701. foreach ($aArgs as $arg) {
  702. if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  703. $arg = (integer) $arg;
  704. }
  705. // Is it a numeric value?
  706. if ((is_numeric($arg)) && (!is_string($arg))) {
  707. if (is_null($returnValue)) {
  708. $returnValue = $arg;
  709. } else {
  710. $returnValue += $arg;
  711. }
  712. ++$aCount;
  713. }
  714. }
  715. // Return
  716. if ($aCount > 0) {
  717. return $returnValue / $aCount;
  718. } else {
  719. return self::$_errorCodes['divisionbyzero'];
  720. }
  721. }
  722. /**
  723. * AVERAGEA
  724. *
  725. * Returns the average of its arguments, including numbers, text, and logical values
  726. *
  727. * @param array of mixed Data Series
  728. * @return float
  729. */
  730. public static function AVERAGEA() {
  731. // Return value
  732. $returnValue = null;
  733. // Loop through arguments
  734. $aArgs = self::flattenArray(func_get_args());
  735. $aCount = 0;
  736. foreach ($aArgs as $arg) {
  737. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  738. if (is_bool($arg)) {
  739. $arg = (integer) $arg;
  740. } elseif (is_string($arg)) {
  741. $arg = 0;
  742. }
  743. if (is_null($returnValue)) {
  744. $returnValue = $arg;
  745. } else {
  746. $returnValue += $arg;
  747. }
  748. ++$aCount;
  749. }
  750. }
  751. // Return
  752. if ($aCount > 0) {
  753. return $returnValue / $aCount;
  754. } else {
  755. return self::$_errorCodes['divisionbyzero'];
  756. }
  757. }
  758. /**
  759. * MEDIAN
  760. *
  761. * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
  762. *
  763. * @param array of mixed Data Series
  764. * @return float
  765. */
  766. public static function MEDIAN() {
  767. // Return value
  768. $returnValue = self::$_errorCodes['num'];
  769. $mArgs = array();
  770. // Loop through arguments
  771. $aArgs = self::flattenArray(func_get_args());
  772. foreach ($aArgs as $arg) {
  773. // Is it a numeric value?
  774. if ((is_numeric($arg)) && (!is_string($arg))) {
  775. $mArgs[] = $arg;
  776. }
  777. }
  778. $mValueCount = count($mArgs);
  779. if ($mValueCount > 0) {
  780. sort($mArgs,SORT_NUMERIC);
  781. $mValueCount = $mValueCount / 2;
  782. if ($mValueCount == floor($mValueCount)) {
  783. $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
  784. } else {
  785. $mValueCount == floor($mValueCount);
  786. $returnValue = $mArgs[$mValueCount];
  787. }
  788. }
  789. // Return
  790. return $returnValue;
  791. }
  792. //
  793. // Special variant of array_count_values that isn't limited to strings and integers,
  794. // but can work with floating point numbers as values
  795. //
  796. private static function modeCalc($data) {
  797. $frequencyArray = array();
  798. foreach($data as $datum) {
  799. $found = False;
  800. foreach($frequencyArray as $key => $value) {
  801. if ((string)$value['value'] == (string)$datum) {
  802. ++$frequencyArray[$key]['frequency'];
  803. $found = True;
  804. break;
  805. }
  806. }
  807. if (!$found) {
  808. $frequencyArray[] = array('value' => $datum,
  809. 'frequency' => 1 );
  810. }
  811. }
  812. foreach($frequencyArray as $key => $value) {
  813. $frequencyList[$key] = $value['frequency'];
  814. $valueList[$key] = $value['value'];
  815. }
  816. array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
  817. if ($frequencyArray[0]['frequency'] == 1) {
  818. return self::NA();
  819. }
  820. return $frequencyArray[0]['value'];
  821. }
  822. /**
  823. * MODE
  824. *
  825. * Returns the most frequently occurring, or repetitive, value in an array or range of data
  826. *
  827. * @param array of mixed Data Series
  828. * @return float
  829. */
  830. public static function MODE() {
  831. // Return value
  832. $returnValue = self::NA();
  833. // Loop through arguments
  834. $aArgs = self::flattenArray(func_get_args());
  835. $mArgs = array();
  836. foreach ($aArgs as $arg) {
  837. // Is it a numeric value?
  838. if ((is_numeric($arg)) && (!is_string($arg))) {
  839. $mArgs[] = $arg;
  840. }
  841. }
  842. if (count($mArgs) > 0) {
  843. return self::modeCalc($mArgs);
  844. }
  845. // Return
  846. return $returnValue;
  847. }
  848. /**
  849. * DEVSQ
  850. *
  851. * Returns the sum of squares of deviations of data points from their sample mean.
  852. *
  853. * @param array of mixed Data Series
  854. * @return float
  855. */
  856. public static function DEVSQ() {
  857. // Return value
  858. $returnValue = null;
  859. $aMean = self::AVERAGE(func_get_args());
  860. if (!is_null($aMean)) {
  861. $aArgs = self::flattenArray(func_get_args());
  862. $aCount = -1;
  863. foreach ($aArgs as $arg) {
  864. // Is it a numeric value?
  865. if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  866. $arg = (int) $arg;
  867. }
  868. if ((is_numeric($arg)) && (!is_string($arg))) {
  869. if (is_null($returnValue)) {
  870. $returnValue = pow(($arg - $aMean),2);
  871. } else {
  872. $returnValue += pow(($arg - $aMean),2);
  873. }
  874. ++$aCount;
  875. }
  876. }
  877. // Return
  878. if (is_null($returnValue)) {
  879. return self::$_errorCodes['num'];
  880. } else {
  881. return $returnValue;
  882. }
  883. }
  884. return self::NA();
  885. }
  886. /**
  887. * AVEDEV
  888. *
  889. * Returns the average of the absolute deviations of data points from their mean.
  890. * AVEDEV is a measure of the variability in a data set.
  891. *
  892. * @param array of mixed Data Series
  893. * @return float
  894. */
  895. public static function AVEDEV() {
  896. $aArgs = self::flattenArray(func_get_args());
  897. // Return value
  898. $returnValue = null;
  899. $aMean = self::AVERAGE($aArgs);
  900. if ($aMean != self::$_errorCodes['divisionbyzero']) {
  901. $aCount = 0;
  902. foreach ($aArgs as $arg) {
  903. if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  904. $arg = (integer) $arg;
  905. }
  906. // Is it a numeric value?
  907. if ((is_numeric($arg)) && (!is_string($arg))) {
  908. if (is_null($returnValue)) {
  909. $returnValue = abs($arg - $aMean);
  910. } else {
  911. $returnValue += abs($arg - $aMean);
  912. }
  913. ++$aCount;
  914. }
  915. }
  916. // Return
  917. return $returnValue / $aCount ;
  918. }
  919. return self::$_errorCodes['num'];
  920. }
  921. /**
  922. * GEOMEAN
  923. *
  924. * Returns the geometric mean of an array or range of positive data. For example, you
  925. * can use GEOMEAN to calculate average growth rate given compound interest with
  926. * variable rates.
  927. *
  928. * @param array of mixed Data Series
  929. * @return float
  930. */
  931. public static function GEOMEAN() {
  932. $aMean = self::PRODUCT(func_get_args());
  933. if (is_numeric($aMean) && ($aMean > 0)) {
  934. $aArgs = self::flattenArray(func_get_args());
  935. $aCount = self::COUNT($aArgs) ;
  936. if (self::MIN($aArgs) > 0) {
  937. return pow($aMean, (1 / $aCount));
  938. }
  939. }
  940. return self::$_errorCodes['num'];
  941. }
  942. /**
  943. * HARMEAN
  944. *
  945. * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
  946. * arithmetic mean of reciprocals.
  947. *
  948. * @param array of mixed Data Series
  949. * @return float
  950. */
  951. public static function HARMEAN() {
  952. // Return value
  953. $returnValue = self::NA();
  954. // Loop through arguments
  955. $aArgs = self::flattenArray(func_get_args());
  956. if (self::MIN($aArgs) < 0) {
  957. return self::$_errorCodes['num'];
  958. }
  959. $aCount = 0;
  960. foreach ($aArgs as $arg) {
  961. // Is it a numeric value?
  962. if ((is_numeric($arg)) && (!is_string($arg))) {
  963. if ($arg <= 0) {
  964. return self::$_errorCodes['num'];
  965. }
  966. if (is_null($returnValue)) {
  967. $returnValue = (1 / $arg);
  968. } else {
  969. $returnValue += (1 / $arg);
  970. }
  971. ++$aCount;
  972. }
  973. }
  974. // Return
  975. if ($aCount > 0) {
  976. return 1 / ($returnValue / $aCount);
  977. } else {
  978. return $returnValue;
  979. }
  980. }
  981. /**
  982. * TRIMMEAN
  983. *
  984. * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
  985. * taken by excluding a percentage of data points from the top and bottom tails
  986. * of a data set.
  987. *
  988. * @param array of mixed Data Series
  989. * @param float Percentage to discard
  990. * @return float
  991. */
  992. public static function TRIMMEAN() {
  993. $aArgs = self::flattenArray(func_get_args());
  994. // Calculate
  995. $percent = array_pop($aArgs);
  996. if ((is_numeric($percent)) && (!is_string($percent))) {
  997. if (($percent < 0) || ($percent > 1)) {
  998. return self::$_errorCodes['num'];
  999. }
  1000. $mArgs = array();
  1001. foreach ($aArgs as $arg) {
  1002. // Is it a numeric value?
  1003. if ((is_numeric($arg)) && (!is_string($arg))) {
  1004. $mArgs[] = $arg;
  1005. }
  1006. }
  1007. $discard = floor(self::COUNT($mArgs) * $percent / 2);
  1008. sort($mArgs);
  1009. for ($i=0; $i < $discard; ++$i) {
  1010. array_pop($mArgs);
  1011. array_shift($mArgs);
  1012. }
  1013. return self::AVERAGE($mArgs);
  1014. }
  1015. return self::$_errorCodes['value'];
  1016. }
  1017. /**
  1018. * STDEV
  1019. *
  1020. * Estimates standard deviation based on a sample. The standard deviation is a measure of how
  1021. * widely values are dispersed from the average value (the mean).
  1022. *
  1023. * @param array of mixed Data Series
  1024. * @return float
  1025. */
  1026. public static function STDEV() {
  1027. // Return value
  1028. $returnValue = null;
  1029. $aMean = self::AVERAGE(func_get_args());
  1030. if (!is_null($aMean)) {
  1031. $aArgs = self::flattenArray(func_get_args());
  1032. $aCount = -1;
  1033. foreach ($aArgs as $arg) {
  1034. // Is it a numeric value?
  1035. if ((is_numeric($arg)) && (!is_string($arg))) {
  1036. if (is_null($returnValue)) {
  1037. $returnValue = pow(($arg - $aMean),2);
  1038. } else {
  1039. $returnValue += pow(($arg - $aMean),2);
  1040. }
  1041. ++$aCount;
  1042. }
  1043. }
  1044. // Return
  1045. if (($aCount > 0) && ($returnValue > 0)) {
  1046. return sqrt($returnValue / $aCount);
  1047. }
  1048. }
  1049. return self::$_errorCodes['divisionbyzero'];
  1050. }
  1051. /**
  1052. * STDEVA
  1053. *
  1054. * Estimates standard deviation based on a sample, including numbers, text, and logical values
  1055. *
  1056. * @param array of mixed Data Series
  1057. * @return float
  1058. */
  1059. public static function STDEVA() {
  1060. // Return value
  1061. $returnValue = null;
  1062. $aMean = self::AVERAGEA(func_get_args());
  1063. if (!is_null($aMean)) {
  1064. $aArgs = self::flattenArray(func_get_args());
  1065. $aCount = -1;
  1066. foreach ($aArgs as $arg) {
  1067. // Is it a numeric value?
  1068. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  1069. if (is_bool($arg)) {
  1070. $arg = (integer) $arg;
  1071. } elseif (is_string($arg)) {
  1072. $arg = 0;
  1073. }
  1074. if (is_null($returnValue)) {
  1075. $returnValue = pow(($arg - $aMean),2);
  1076. } else {
  1077. $returnValue += pow(($arg - $aMean),2);
  1078. }
  1079. ++$aCount;
  1080. }
  1081. }
  1082. // Return
  1083. if (($aCount > 0) && ($returnValue > 0)) {
  1084. return sqrt($returnValue / $aCount);
  1085. }
  1086. }
  1087. return self::$_errorCodes['divisionbyzero'];
  1088. }
  1089. /**
  1090. * STDEVP
  1091. *
  1092. * Calculates standard deviation based on the entire population
  1093. *
  1094. * @param array of mixed Data Series
  1095. * @return float
  1096. */
  1097. public static function STDEVP() {
  1098. // Return value
  1099. $returnValue = null;
  1100. $aMean = self::AVERAGE(func_get_args());
  1101. if (!is_null($aMean)) {
  1102. $aArgs = self::flattenArray(func_get_args());
  1103. $aCount = 0;
  1104. foreach ($aArgs as $arg) {
  1105. // Is it a numeric value?
  1106. if ((is_numeric($arg)) && (!is_string($arg))) {
  1107. if (is_null($returnValue)) {
  1108. $returnValue = pow(($arg - $aMean),2);
  1109. } else {
  1110. $returnValue += pow(($arg - $aMean),2);
  1111. }
  1112. ++$aCount;
  1113. }
  1114. }
  1115. // Return
  1116. if (($aCount > 0) && ($returnValue > 0)) {
  1117. return sqrt($returnValue / $aCount);
  1118. }
  1119. }
  1120. return self::$_errorCodes['divisionbyzero'];
  1121. }
  1122. /**
  1123. * STDEVPA
  1124. *
  1125. * Calculates standard deviation based on the entire population, including numbers, text, and logical values
  1126. *
  1127. * @param array of mixed Data Series
  1128. * @return float
  1129. */
  1130. public static function STDEVPA() {
  1131. // Return value
  1132. $returnValue = null;
  1133. $aMean = self::AVERAGEA(func_get_args());
  1134. if (!is_null($aMean)) {
  1135. $aArgs = self::flattenArray(func_get_args());
  1136. $aCount = 0;
  1137. foreach ($aArgs as $arg) {
  1138. // Is it a numeric value?
  1139. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  1140. if (is_bool($arg)) {
  1141. $arg = (integer) $arg;
  1142. } elseif (is_string($arg)) {
  1143. $arg = 0;
  1144. }
  1145. if (is_null($returnValue)) {
  1146. $returnValue = pow(($arg - $aMean),2);
  1147. } else {
  1148. $returnValue += pow(($arg - $aMean),2);
  1149. }
  1150. ++$aCount;
  1151. }
  1152. }
  1153. // Return
  1154. if (($aCount > 0) && ($returnValue > 0)) {
  1155. return sqrt($returnValue / $aCount);
  1156. }
  1157. }
  1158. return self::$_errorCodes['divisionbyzero'];
  1159. }
  1160. /**
  1161. * VARFunc
  1162. *
  1163. * Estimates variance based on a sample.
  1164. *
  1165. * @param array of mixed Data Series
  1166. * @return float
  1167. */
  1168. public static function VARFunc() {
  1169. // Return value
  1170. $returnValue = self::$_errorCodes['divisionbyzero'];
  1171. $summerA = $summerB = 0;
  1172. // Loop through arguments
  1173. $aArgs = self::flattenArray(func_get_args());
  1174. $aCount = 0;
  1175. foreach ($aArgs as $arg) {
  1176. // Is it a numeric value?
  1177. if ((is_numeric($arg)) && (!is_string($arg))) {
  1178. $summerA += ($arg * $arg);
  1179. $summerB += $arg;
  1180. ++$aCount;
  1181. }
  1182. }
  1183. // Return
  1184. if ($aCount > 1) {
  1185. $summerA = $summerA * $aCount;
  1186. $summerB = ($summerB * $summerB);
  1187. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  1188. }
  1189. return $returnValue;
  1190. }
  1191. /**
  1192. * VARA
  1193. *
  1194. * Estimates variance based on a sample, including numbers, text, and logical values
  1195. *
  1196. * @param array of mixed Data Series
  1197. * @return float
  1198. */
  1199. public static function VARA() {
  1200. // Return value
  1201. $returnValue = self::$_errorCodes['divisionbyzero'];
  1202. $summerA = $summerB = 0;
  1203. // Loop through arguments
  1204. $aArgs = self::flattenArray(func_get_args());
  1205. $aCount = 0;
  1206. foreach ($aArgs as $arg) {
  1207. // Is it a numeric value?
  1208. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  1209. if (is_bool($arg)) {
  1210. $arg = (integer) $arg;
  1211. } elseif (is_string($arg)) {
  1212. $arg = 0;
  1213. }
  1214. $summerA += ($arg * $arg);
  1215. $summerB += $arg;
  1216. ++$aCount;
  1217. }
  1218. }
  1219. // Return
  1220. if ($aCount > 1) {
  1221. $summerA = $summerA * $aCount;
  1222. $summerB = ($summerB * $summerB);
  1223. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  1224. }
  1225. return $returnValue;
  1226. }
  1227. /**
  1228. * VARP
  1229. *
  1230. * Calculates variance based on the entire population
  1231. *
  1232. * @param array of mixed Data Series
  1233. * @return float
  1234. */
  1235. public static function VARP() {
  1236. // Return value
  1237. $returnValue = self::$_errorCodes['divisionbyzero'];
  1238. $summerA = $summerB = 0;
  1239. // Loop through arguments
  1240. $aArgs = self::flattenArray(func_get_args());
  1241. $aCount = 0;
  1242. foreach ($aArgs as $arg) {
  1243. // Is it a numeric value?
  1244. if ((is_numeric($arg)) && (!is_string($arg))) {
  1245. $summerA += ($arg * $arg);
  1246. $summerB += $arg;
  1247. ++$aCount;
  1248. }
  1249. }
  1250. // Return
  1251. if ($aCount > 0) {
  1252. $summerA = $summerA * $aCount;
  1253. $summerB = ($summerB * $summerB);
  1254. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  1255. }
  1256. return $returnValue;
  1257. }
  1258. /**
  1259. * VARPA
  1260. *
  1261. * Calculates variance based on the entire population, including numbers, text, and logical values
  1262. *
  1263. * @param array of mixed Data Series
  1264. * @return float
  1265. */
  1266. public static function VARPA() {
  1267. // Return value
  1268. $returnValue = self::$_errorCodes['divisionbyzero'];
  1269. $summerA = $summerB = 0;
  1270. // Loop through arguments
  1271. $aArgs = self::flattenArray(func_get_args());
  1272. $aCount = 0;
  1273. foreach ($aArgs as $arg) {
  1274. // Is it a numeric value?
  1275. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  1276. if (is_bool($arg)) {
  1277. $arg = (integer) $arg;
  1278. } elseif (is_string($arg)) {
  1279. $arg = 0;
  1280. }
  1281. $summerA += ($arg * $arg);
  1282. $summerB += $arg;
  1283. ++$aCount;
  1284. }
  1285. }
  1286. // Return
  1287. if ($aCount > 0) {
  1288. $summerA = $summerA * $aCount;
  1289. $summerB = ($summerB * $summerB);
  1290. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  1291. }
  1292. return $returnValue;
  1293. }
  1294. /**
  1295. * SUBTOTAL
  1296. *
  1297. * Returns a subtotal in a list or database.
  1298. *
  1299. * @param int the number 1 to 11 that specifies which function to
  1300. * use in calculating subtotals within a list.
  1301. * @param array of mixed Data Series
  1302. * @return float
  1303. */
  1304. public static function SUBTOTAL() {
  1305. $aArgs = self::flattenArray(func_get_args());
  1306. // Calculate
  1307. $subtotal = array_shift($aArgs);
  1308. if ((is_numeric($subtotal)) && (!is_string($subtotal))) {
  1309. switch($subtotal) {
  1310. case 1 :
  1311. return self::AVERAGE($aArgs);
  1312. break;
  1313. case 2 :
  1314. return self::COUNT($aArgs);
  1315. break;
  1316. case 3 :
  1317. return self::COUNTA($aArgs);
  1318. break;
  1319. case 4 :
  1320. return self::MAX($aArgs);
  1321. break;
  1322. case 5 :
  1323. return self::MIN($aArgs);
  1324. break;
  1325. case 6 :
  1326. return self::PRODUCT($aArgs);
  1327. break;
  1328. case 7 :
  1329. return self::STDEV($aArgs);
  1330. break;
  1331. case 8 :
  1332. return self::STDEVP($aArgs);
  1333. break;
  1334. case 9 :
  1335. return self::SUM($aArgs);
  1336. break;
  1337. case 10 :
  1338. return self::VARFunc($aArgs);
  1339. break;
  1340. case 11 :
  1341. return self::VARP($aArgs);
  1342. break;
  1343. }
  1344. }
  1345. return self::$_errorCodes['value'];
  1346. }
  1347. /**
  1348. * SQRTPI
  1349. *
  1350. * Returns the square root of (number * pi).
  1351. *
  1352. * @param float $number Number
  1353. * @return float Square Root of Number * Pi
  1354. */
  1355. public static function SQRTPI($number) {
  1356. $number = self::flattenSingleValue($number);
  1357. if (is_numeric($number)) {
  1358. if ($number < 0) {
  1359. return self::$_errorCodes['num'];
  1360. }
  1361. return sqrt($number * pi()) ;
  1362. }
  1363. return self::$_errorCodes['value'];
  1364. }
  1365. /**
  1366. * FACT
  1367. *
  1368. * Returns the factorial of a number.
  1369. *
  1370. * @param float $factVal Factorial Value
  1371. * @return int Factorial
  1372. */
  1373. public static function FACT($factVal) {
  1374. $factVal = self::flattenSingleValue($factVal);
  1375. if (is_numeric($factVal)) {
  1376. if ($factVal < 0) {
  1377. return self::$_errorCodes['num'];
  1378. }
  1379. $factLoop = floor($factVal);
  1380. if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) {
  1381. if ($factVal > $factLoop) {
  1382. return self::$_errorCodes['num'];
  1383. }
  1384. }
  1385. $factorial = 1;
  1386. while ($factLoop > 1) {
  1387. $factorial *= $factLoop--;
  1388. }
  1389. return $factorial ;
  1390. }
  1391. return self::$_errorCodes['value'];
  1392. }
  1393. /**
  1394. * FACTDOUBLE
  1395. *
  1396. * Returns the double factorial of a number.
  1397. *
  1398. * @param float $factVal Factorial Value
  1399. * @return int Double Factorial
  1400. */
  1401. public static function FACTDOUBLE($factVal) {
  1402. $factLoop = floor(self::flattenSingleValue($factVal));
  1403. if (is_numeric($factLoop)) {
  1404. if ($factVal < 0) {
  1405. return self::$_errorCodes['num'];
  1406. }
  1407. $factorial = 1;
  1408. while ($factLoop > 1) {
  1409. $factorial *= $factLoop--;
  1410. --$factLoop;
  1411. }
  1412. return $factorial ;
  1413. }
  1414. return self::$_errorCodes['value'];
  1415. }
  1416. /**
  1417. * MULTINOMIAL
  1418. *
  1419. * Returns the ratio of the factorial of a sum of values to the product of factorials.
  1420. *
  1421. * @param array of mixed Data Series
  1422. * @return float
  1423. */
  1424. public static function MULTINOMIAL() {
  1425. // Loop through arguments
  1426. $aArgs = self::flattenArray(func_get_args());
  1427. $summer = 0;
  1428. $divisor = 1;
  1429. foreach ($aArgs as $arg) {
  1430. // Is it a numeric value?
  1431. if (is_numeric($arg)) {
  1432. if ($arg < 1) {
  1433. return self::$_errorCodes['num'];
  1434. }
  1435. $summer += floor($arg);
  1436. $divisor *= self::FACT($arg);
  1437. } else {
  1438. return self::$_errorCodes['value'];
  1439. }
  1440. }
  1441. // Return
  1442. if ($summer > 0) {
  1443. $summer = self::FACT($summer);
  1444. return $summer / $divisor;
  1445. }
  1446. return 0;
  1447. }
  1448. /**
  1449. * CEILING
  1450. *
  1451. * Returns number rounded up, away from zero, to the nearest multiple of significance.
  1452. *
  1453. * @param float $number Number to round
  1454. * @param float $significance Significance
  1455. * @return float Rounded Number
  1456. */
  1457. public static function CEILING($number,$significance=null) {
  1458. $number = self::flattenSingleValue($number);
  1459. $significance = self::flattenSingleValue($significance);
  1460. if ((is_null($significance)) && (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC)) {
  1461. $significance = $number/abs($number);
  1462. }
  1463. if ((is_numeric($number)) && (is_numeric($significance))) {
  1464. if (self::SIGN($number) == self::SIGN($significance)) {
  1465. if ($significance == 0.0) {
  1466. return 0;
  1467. }
  1468. return ceil($number / $significance) * $significance;
  1469. } else {
  1470. return self::$_errorCodes['num'];
  1471. }
  1472. }
  1473. return self::$_errorCodes['value'];
  1474. }
  1475. /**
  1476. * EVEN
  1477. *
  1478. * Returns number rounded up to the nearest even integer.
  1479. *
  1480. * @param float $number Number to round
  1481. * @return int Rounded Number
  1482. */
  1483. public static function EVEN($number) {
  1484. $number = self::flattenSingleValue($number);
  1485. if (is_numeric($number)) {
  1486. $significance = 2 * self::SIGN($number);
  1487. return self::CEILING($number,$significance);
  1488. }
  1489. return self::$_errorCodes['value'];
  1490. }
  1491. /**
  1492. * ODD
  1493. *
  1494. * Returns number rounded up to the nearest odd integer.
  1495. *
  1496. * @param float $number Number to round
  1497. * @return int Rounded Number
  1498. */
  1499. public static function ODD($number) {
  1500. $number = self::flattenSingleValue($number);
  1501. if (is_numeric($number)) {
  1502. $significance = self::SIGN($number);
  1503. if ($significance == 0) {
  1504. return 1;
  1505. }
  1506. $result = self::CEILING($number,$significance);
  1507. if (self::IS_EVEN($result)) {
  1508. $result += $significance;
  1509. }
  1510. return $result;
  1511. }
  1512. return self::$_errorCodes['value'];
  1513. }
  1514. /**
  1515. * ROUNDUP
  1516. *
  1517. * Rounds a number up to a specified number of decimal places
  1518. *
  1519. * @param float $number Number to round
  1520. * @param int $digits Number of digits to which you want to round $number
  1521. * @return float Rounded Number
  1522. */
  1523. public static function ROUNDUP($number,$digits) {
  1524. $number = self::flattenSingleValue($number);
  1525. $digits = self::flattenSingleValue($digits);
  1526. if (is_numeric($number)) {
  1527. if ((is_numeric($digits)) && ($digits >= 0)) {
  1528. $significance = pow(10,$digits);
  1529. return ceil($number * $significance) / $significance;
  1530. }
  1531. }
  1532. return self::$_errorCodes['value'];
  1533. }
  1534. /**
  1535. * ROUNDDOWN
  1536. *
  1537. * Rounds a number down to a specified number of decimal places
  1538. *
  1539. * @param float $number Number to round
  1540. * @param int $digits Number of digits to which you want to round $number
  1541. * @return float Rounded Number
  1542. */
  1543. public static function ROUNDDOWN($number,$digits) {
  1544. $number = self::flattenSingleValue($number);
  1545. $digits = self::flattenSingleValue($digits);
  1546. if (is_numeric($number)) {
  1547. if ((is_numeric($digits)) && ($digits >= 0)) {
  1548. $significance = pow(10,$digits);
  1549. return floor($number * $significance) / $significance;
  1550. }
  1551. }
  1552. return self::$_errorCodes['value'];
  1553. }
  1554. /**
  1555. * MROUND
  1556. *
  1557. * Rounds a number to the nearest multiple of a specified value
  1558. *
  1559. * @param float $number Number to round
  1560. * @param int $multiple Multiple to which you want to round $number
  1561. * @return float Rounded Number
  1562. */
  1563. public static function MROUND($number,$multiple) {
  1564. $number = self::flattenSingleValue($number);
  1565. $multiple = self::flattenSingleValue($multiple);
  1566. if ((is_numeric($number)) && (is_numeric($multiple))) {
  1567. if ((self::SIGN($number)) == (self::SIGN($multiple))) {
  1568. $lowerVal = floor($number / $multiple) * $multiple;
  1569. $upperVal = ceil($number / $multiple) * $multiple;
  1570. $adjustUp = abs($number - $upperVal);
  1571. $adjustDown = abs($number - $lowerVal) + PRECISION;
  1572. if ($adjustDown < $adjustUp) {
  1573. return $lowerVal;
  1574. }
  1575. return $upperVal;
  1576. }
  1577. return self::$_errorCodes['num'];
  1578. }
  1579. return self::$_errorCodes['value'];
  1580. }
  1581. /**
  1582. * SIGN
  1583. *
  1584. * Determines the sign of a number. Returns 1 if the number is positive, zero (0)
  1585. * if the number is 0, and -1 if the number is negative.
  1586. *
  1587. * @param float $number Number to round
  1588. * @return int sign value
  1589. */
  1590. public static function SIGN($number) {
  1591. $number = self::flattenSingleValue($number);
  1592. if (is_numeric($number)) {
  1593. if ($number == 0.0) {
  1594. return 0;
  1595. }
  1596. return $number / abs($number);
  1597. }
  1598. return self::$_errorCodes['value'];
  1599. }
  1600. /**
  1601. * FLOOR
  1602. *
  1603. * Rounds number down, toward zero, to the nearest multiple of significance.
  1604. *
  1605. * @param float $number Number to round
  1606. * @param float $significance Significance
  1607. * @return float Rounded Number
  1608. */
  1609. public static function FLOOR($number,$significance=null) {
  1610. $number = self::flattenSingleValue($number);
  1611. $significance = self::flattenSingleValue($significance);
  1612. if ((is_null($significance)) && (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC)) {
  1613. $significance = $number/abs($number);
  1614. }
  1615. if ((is_numeric($number)) && (is_numeric($significance))) {
  1616. if ((float) $significance == 0.0) {
  1617. return self::$_errorCodes['divisionbyzero'];
  1618. }
  1619. if (self::SIGN($number) == self::SIGN($significance)) {
  1620. return floor($number / $significance) * $significance;
  1621. } else {
  1622. return self::$_errorCodes['num'];
  1623. }
  1624. }
  1625. return self::$_errorCodes['value'];
  1626. }
  1627. /**
  1628. * PERMUT
  1629. *
  1630. * Returns the number of permutations for a given number of objects that can be
  1631. * selected from number objects. A permutation is any set or subset of objects or
  1632. * events where internal order is significant. Permutations are different from
  1633. * combinations, for which the internal order is not significant. Use this function
  1634. * for lottery-style probability calculations.
  1635. *
  1636. * @param int $numObjs Number of different objects
  1637. * @param int $numInSet Number of objects in each permutation
  1638. * @return int Number of permutations
  1639. */
  1640. public static function PERMUT($numObjs,$numInSet) {
  1641. $numObjs = self::flattenSingleValue($numObjs);
  1642. $numInSet = self::flattenSingleValue($numInSet);
  1643. if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
  1644. if ($numObjs < $numInSet) {
  1645. return self::$_errorCodes['num'];
  1646. }
  1647. return self::FACT($numObjs) / self::FACT($numObjs - $numInSet);
  1648. }
  1649. return self::$_errorCodes['value'];
  1650. }
  1651. /**
  1652. * COMBIN
  1653. *
  1654. * Returns the number of combinations for a given number of items. Use COMBIN to
  1655. * determine the total possible number of groups for a given number of items.
  1656. *
  1657. * @param int $numObjs Number of different objects
  1658. * @param int $numInSet Number of objects in each combination
  1659. * @return int Number of combinations
  1660. */
  1661. public static function COMBIN($numObjs,$numInSet) {
  1662. $numObjs = self::flattenSingleValue($numObjs);
  1663. $numInSet = self::flattenSingleValue($numInSet);
  1664. if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
  1665. if ($numObjs < $numInSet) {
  1666. return self::$_errorCodes['num'];
  1667. } elseif ($numInSet < 0) {
  1668. return self::$_errorCodes['num'];
  1669. }
  1670. return (self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet);
  1671. }
  1672. return self::$_errorCodes['value'];
  1673. }
  1674. /**
  1675. * SERIESSUM
  1676. *
  1677. * Returns the sum of a power series
  1678. *
  1679. * @param float $x Input value to the power series
  1680. * @param float $n Initial power to which you want to raise $x
  1681. * @param float $m Step by which to increase $n for each term in the series
  1682. * @param array of mixed Data Series
  1683. * @return float
  1684. */
  1685. public static function SERIESSUM() {
  1686. // Return value
  1687. $returnValue = 0;
  1688. // Loop trough arguments
  1689. $aArgs = self::flattenArray(func_get_args());
  1690. $x = array_shift($aArgs);
  1691. $n = array_shift($aArgs);
  1692. $m = array_shift($aArgs);
  1693. if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) {
  1694. // Calculate
  1695. $i = 0;
  1696. foreach($aArgs as $arg) {
  1697. // Is it a numeric value?
  1698. if ((is_numeric($arg)) && (!is_string($arg))) {
  1699. $returnValue += $arg * pow($x,$n + ($m * $i++));
  1700. } else {
  1701. return self::$_errorCodes['value'];
  1702. }
  1703. }
  1704. // Return
  1705. return $returnValue;
  1706. }
  1707. return self::$_errorCodes['value'];
  1708. }
  1709. /**
  1710. * STANDARDIZE
  1711. *
  1712. * Returns a normalized value from a distribution characterized by mean and standard_dev.
  1713. *
  1714. * @param float $value Value to normalize
  1715. * @param float $mean Mean Value
  1716. * @param float $stdDev Standard Deviation
  1717. * @return float Standardized value
  1718. */
  1719. public static function STANDARDIZE($value,$mean,$stdDev) {
  1720. $value = self::flattenSingleValue($value);
  1721. $mean = self::flattenSingleValue($mean);
  1722. $stdDev = self::flattenSingleValue($stdDev);
  1723. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  1724. if ($stdDev <= 0) {
  1725. return self::$_errorCodes['num'];
  1726. }
  1727. return ($value - $mean) / $stdDev ;
  1728. }
  1729. return self::$_errorCodes['value'];
  1730. }
  1731. //
  1732. // Private method to return an array of the factors of the input value
  1733. //
  1734. private static function factors($value) {
  1735. $startVal = floor(sqrt($value));
  1736. $factorArray = array();
  1737. for ($i = $startVal; $i > 1; --$i) {
  1738. if (($value % $i) == 0) {
  1739. $factorArray = array_merge($factorArray,self::factors($value / $i));
  1740. $factorArray = array_merge($factorArray,self::factors($i));
  1741. if ($i <= sqrt($value)) {
  1742. break;
  1743. }
  1744. }
  1745. }
  1746. if (count($factorArray) > 0) {
  1747. rsort($factorArray);
  1748. return $factorArray;
  1749. } else {
  1750. return array((integer) $value);
  1751. }
  1752. }
  1753. /**
  1754. * LCM
  1755. *
  1756. * Returns the lowest common multiplier of a series of numbers
  1757. *
  1758. * @param $array Values to calculate the Lowest Common Multiplier
  1759. * @return int Lowest Common Multiplier
  1760. */
  1761. public static function LCM() {
  1762. $aArgs = self::flattenArray(func_get_args());
  1763. $returnValue = 1;
  1764. $allPoweredFactors = array();
  1765. foreach($aArgs as $value) {
  1766. if (!is_numeric($value)) {
  1767. return self::$_errorCodes['value'];
  1768. }
  1769. if ($value < 1) {
  1770. return self::$_errorCodes['num'];
  1771. }
  1772. $myFactors = self::factors(floor($value));
  1773. $myCountedFactors = array_count_values($myFactors);
  1774. $myPoweredFactors = array();
  1775. foreach($myCountedFactors as $myCountedFactor => $myCountedPower) {
  1776. $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor,$myCountedPower);
  1777. }
  1778. foreach($myPoweredFactors as $myPoweredValue => $myPoweredFactor) {
  1779. if (array_key_exists($myPoweredValue,$allPoweredFactors)) {
  1780. if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) {
  1781. $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
  1782. }
  1783. } else {
  1784. $allPoweredFactors[$myPoweredValue] = $myPoweredFactor;
  1785. }
  1786. }
  1787. }
  1788. foreach($allPoweredFactors as $allPoweredFactor) {
  1789. $returnValue *= (integer) $allPoweredFactor;
  1790. }
  1791. return $returnValue;
  1792. }
  1793. /**
  1794. * GCD
  1795. *
  1796. * Returns the greatest common divisor of a series of numbers
  1797. *
  1798. * @param $array Values to calculate the Greatest Common Divisor
  1799. * @return int Greatest Common Divisor
  1800. */
  1801. public static function GCD() {
  1802. $aArgs = self::flattenArray(func_get_args());
  1803. $returnValue = 1;
  1804. $allPoweredFactors = array();
  1805. foreach($aArgs as $value) {
  1806. if ($value == 0) {
  1807. return 0;
  1808. }
  1809. $myFactors = self::factors($value);
  1810. $myCountedFactors = array_count_values($myFactors);
  1811. $allValuesFactors[] = $myCountedFactors;
  1812. }
  1813. $allValuesCount = count($allValuesFactors);
  1814. $mergedArray = $allValuesFactors[0];
  1815. for ($i=1;$i < $allValuesCount; ++$i) {
  1816. $mergedArray = array_intersect_key($mergedArray,$allValuesFactors[$i]);
  1817. }
  1818. $mergedArrayValues = count($mergedArray);
  1819. if ($mergedArrayValues == 0) {
  1820. return $returnValue;
  1821. } elseif ($mergedArrayValues > 1) {
  1822. foreach($mergedArray as $mergedKey => $mergedValue) {
  1823. foreach($allValuesFactors as $highestPowerTest) {
  1824. foreach($highestPowerTest as $testKey => $testValue) {
  1825. if (($testKey == $mergedKey) && ($testValue < $mergedValue)) {
  1826. $mergedArray[$mergedKey] = $testValue;
  1827. $mergedValue = $testValue;
  1828. }
  1829. }
  1830. }
  1831. }
  1832. $returnValue = 1;
  1833. foreach($mergedArray as $key => $value) {
  1834. $returnValue *= pow($key,$value);
  1835. }
  1836. return $returnValue;
  1837. } else {
  1838. $keys = array_keys($mergedArray);
  1839. $key = $keys[0];
  1840. $value = $mergedArray[$key];
  1841. foreach($allValuesFactors as $testValue) {
  1842. foreach($testValue as $mergedKey => $mergedValue) {
  1843. if (($mergedKey == $key) && ($mergedValue < $value)) {
  1844. $value = $mergedValue;
  1845. }
  1846. }
  1847. }
  1848. return pow($key,$value);
  1849. }
  1850. }
  1851. /**
  1852. * BINOMDIST
  1853. *
  1854. * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
  1855. * a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
  1856. * when trials are independent, and when the probability of success is constant throughout the
  1857. * experiment. For example, BINOMDIST can calculate the probability that two of the next three
  1858. * ba…

Large files files are truncated, but you can click here to view the full file