For God so loved the world, that He gave His only begotten Son, that all who believe in Him should not perish but have everlasting life
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3745 lines
129 KiB

  1. <?php
  2. /** PHPExcel root directory */
  3. if (!defined('PHPEXCEL_ROOT')) {
  4. /**
  5. * @ignore
  6. */
  7. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  8. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  9. }
  10. require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php';
  11. /** LOG_GAMMA_X_MAX_VALUE */
  12. define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
  13. /** XMININ */
  14. define('XMININ', 2.23e-308);
  15. /** EPS */
  16. define('EPS', 2.22e-16);
  17. /** SQRT2PI */
  18. define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
  19. /**
  20. * PHPExcel_Calculation_Statistical
  21. *
  22. * Copyright (c) 2006 - 2015 PHPExcel
  23. *
  24. * This library is free software; you can redistribute it and/or
  25. * modify it under the terms of the GNU Lesser General Public
  26. * License as published by the Free Software Foundation; either
  27. * version 2.1 of the License, or (at your option) any later version.
  28. *
  29. * This library is distributed in the hope that it will be useful,
  30. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  32. * Lesser General Public License for more details.
  33. *
  34. * You should have received a copy of the GNU Lesser General Public
  35. * License along with this library; if not, write to the Free Software
  36. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  37. *
  38. * @category PHPExcel
  39. * @package PHPExcel_Calculation
  40. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  41. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  42. * @version ##VERSION##, ##DATE##
  43. */
  44. class PHPExcel_Calculation_Statistical
  45. {
  46. private static function checkTrendArrays(&$array1, &$array2)
  47. {
  48. if (!is_array($array1)) {
  49. $array1 = array($array1);
  50. }
  51. if (!is_array($array2)) {
  52. $array2 = array($array2);
  53. }
  54. $array1 = PHPExcel_Calculation_Functions::flattenArray($array1);
  55. $array2 = PHPExcel_Calculation_Functions::flattenArray($array2);
  56. foreach ($array1 as $key => $value) {
  57. if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
  58. unset($array1[$key]);
  59. unset($array2[$key]);
  60. }
  61. }
  62. foreach ($array2 as $key => $value) {
  63. if ((is_bool($value)) || (is_string($value)) || (is_null($value))) {
  64. unset($array1[$key]);
  65. unset($array2[$key]);
  66. }
  67. }
  68. $array1 = array_merge($array1);
  69. $array2 = array_merge($array2);
  70. return true;
  71. }
  72. /**
  73. * Beta function.
  74. *
  75. * @author Jaco van Kooten
  76. *
  77. * @param p require p>0
  78. * @param q require q>0
  79. * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
  80. */
  81. private static function beta($p, $q)
  82. {
  83. if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) {
  84. return 0.0;
  85. } else {
  86. return exp(self::logBeta($p, $q));
  87. }
  88. }
  89. /**
  90. * Incomplete beta function
  91. *
  92. * @author Jaco van Kooten
  93. * @author Paul Meagher
  94. *
  95. * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992).
  96. * @param x require 0<=x<=1
  97. * @param p require p>0
  98. * @param q require q>0
  99. * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow
  100. */
  101. private static function incompleteBeta($x, $p, $q)
  102. {
  103. if ($x <= 0.0) {
  104. return 0.0;
  105. } elseif ($x >= 1.0) {
  106. return 1.0;
  107. } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
  108. return 0.0;
  109. }
  110. $beta_gam = exp((0 - self::logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x));
  111. if ($x < ($p + 1.0) / ($p + $q + 2.0)) {
  112. return $beta_gam * self::betaFraction($x, $p, $q) / $p;
  113. } else {
  114. return 1.0 - ($beta_gam * self::betaFraction(1 - $x, $q, $p) / $q);
  115. }
  116. }
  117. // Function cache for logBeta function
  118. private static $logBetaCacheP = 0.0;
  119. private static $logBetaCacheQ = 0.0;
  120. private static $logBetaCacheResult = 0.0;
  121. /**
  122. * The natural logarithm of the beta function.
  123. *
  124. * @param p require p>0
  125. * @param q require q>0
  126. * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow
  127. * @author Jaco van Kooten
  128. */
  129. private static function logBeta($p, $q)
  130. {
  131. if ($p != self::$logBetaCacheP || $q != self::$logBetaCacheQ) {
  132. self::$logBetaCacheP = $p;
  133. self::$logBetaCacheQ = $q;
  134. if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) {
  135. self::$logBetaCacheResult = 0.0;
  136. } else {
  137. self::$logBetaCacheResult = self::logGamma($p) + self::logGamma($q) - self::logGamma($p + $q);
  138. }
  139. }
  140. return self::$logBetaCacheResult;
  141. }
  142. /**
  143. * Evaluates of continued fraction part of incomplete beta function.
  144. * Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
  145. * @author Jaco van Kooten
  146. */
  147. private static function betaFraction($x, $p, $q)
  148. {
  149. $c = 1.0;
  150. $sum_pq = $p + $q;
  151. $p_plus = $p + 1.0;
  152. $p_minus = $p - 1.0;
  153. $h = 1.0 - $sum_pq * $x / $p_plus;
  154. if (abs($h) < XMININ) {
  155. $h = XMININ;
  156. }
  157. $h = 1.0 / $h;
  158. $frac = $h;
  159. $m = 1;
  160. $delta = 0.0;
  161. while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION) {
  162. $m2 = 2 * $m;
  163. // even index for d
  164. $d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2));
  165. $h = 1.0 + $d * $h;
  166. if (abs($h) < XMININ) {
  167. $h = XMININ;
  168. }
  169. $h = 1.0 / $h;
  170. $c = 1.0 + $d / $c;
  171. if (abs($c) < XMININ) {
  172. $c = XMININ;
  173. }
  174. $frac *= $h * $c;
  175. // odd index for d
  176. $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2));
  177. $h = 1.0 + $d * $h;
  178. if (abs($h) < XMININ) {
  179. $h = XMININ;
  180. }
  181. $h = 1.0 / $h;
  182. $c = 1.0 + $d / $c;
  183. if (abs($c) < XMININ) {
  184. $c = XMININ;
  185. }
  186. $delta = $h * $c;
  187. $frac *= $delta;
  188. ++$m;
  189. }
  190. return $frac;
  191. }
  192. /**
  193. * logGamma function
  194. *
  195. * @version 1.1
  196. * @author Jaco van Kooten
  197. *
  198. * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher.
  199. *
  200. * The natural logarithm of the gamma function. <br />
  201. * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz <br />
  202. * Applied Mathematics Division <br />
  203. * Argonne National Laboratory <br />
  204. * Argonne, IL 60439 <br />
  205. * <p>
  206. * References:
  207. * <ol>
  208. * <li>W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural
  209. * Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.</li>
  210. * <li>K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.</li>
  211. * <li>Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.</li>
  212. * </ol>
  213. * </p>
  214. * <p>
  215. * From the original documentation:
  216. * </p>
  217. * <p>
  218. * This routine calculates the LOG(GAMMA) function for a positive real argument X.
  219. * Computation is based on an algorithm outlined in references 1 and 2.
  220. * The program uses rational functions that theoretically approximate LOG(GAMMA)
  221. * to at least 18 significant decimal digits. The approximation for X > 12 is from
  222. * reference 3, while approximations for X < 12.0 are similar to those in reference
  223. * 1, but are unpublished. The accuracy achieved depends on the arithmetic system,
  224. * the compiler, the intrinsic functions, and proper selection of the
  225. * machine-dependent constants.
  226. * </p>
  227. * <p>
  228. * Error returns: <br />
  229. * The program returns the value XINF for X .LE. 0.0 or when overflow would occur.
  230. * The computation is believed to be free of underflow and overflow.
  231. * </p>
  232. * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305
  233. */
  234. // Function cache for logGamma
  235. private static $logGammaCacheResult = 0.0;
  236. private static $logGammaCacheX = 0.0;
  237. private static function logGamma($x)
  238. {
  239. // Log Gamma related constants
  240. static $lg_d1 = -0.5772156649015328605195174;
  241. static $lg_d2 = 0.4227843350984671393993777;
  242. static $lg_d4 = 1.791759469228055000094023;
  243. static $lg_p1 = array(
  244. 4.945235359296727046734888,
  245. 201.8112620856775083915565,
  246. 2290.838373831346393026739,
  247. 11319.67205903380828685045,
  248. 28557.24635671635335736389,
  249. 38484.96228443793359990269,
  250. 26377.48787624195437963534,
  251. 7225.813979700288197698961
  252. );
  253. static $lg_p2 = array(
  254. 4.974607845568932035012064,
  255. 542.4138599891070494101986,
  256. 15506.93864978364947665077,
  257. 184793.2904445632425417223,
  258. 1088204.76946882876749847,
  259. 3338152.967987029735917223,
  260. 5106661.678927352456275255,
  261. 3074109.054850539556250927
  262. );
  263. static $lg_p4 = array(
  264. 14745.02166059939948905062,
  265. 2426813.369486704502836312,
  266. 121475557.4045093227939592,
  267. 2663432449.630976949898078,
  268. 29403789566.34553899906876,
  269. 170266573776.5398868392998,
  270. 492612579337.743088758812,
  271. 560625185622.3951465078242
  272. );
  273. static $lg_q1 = array(
  274. 67.48212550303777196073036,
  275. 1113.332393857199323513008,
  276. 7738.757056935398733233834,
  277. 27639.87074403340708898585,
  278. 54993.10206226157329794414,
  279. 61611.22180066002127833352,
  280. 36351.27591501940507276287,
  281. 8785.536302431013170870835
  282. );
  283. static $lg_q2 = array(
  284. 183.0328399370592604055942,
  285. 7765.049321445005871323047,
  286. 133190.3827966074194402448,
  287. 1136705.821321969608938755,
  288. 5267964.117437946917577538,
  289. 13467014.54311101692290052,
  290. 17827365.30353274213975932,
  291. 9533095.591844353613395747
  292. );
  293. static $lg_q4 = array(
  294. 2690.530175870899333379843,
  295. 639388.5654300092398984238,
  296. 41355999.30241388052042842,
  297. 1120872109.61614794137657,
  298. 14886137286.78813811542398,
  299. 101680358627.2438228077304,
  300. 341747634550.7377132798597,
  301. 446315818741.9713286462081
  302. );
  303. static $lg_c = array(
  304. -0.001910444077728,
  305. 8.4171387781295e-4,
  306. -5.952379913043012e-4,
  307. 7.93650793500350248e-4,
  308. -0.002777777777777681622553,
  309. 0.08333333333333333331554247,
  310. 0.0057083835261
  311. );
  312. // Rough estimate of the fourth root of logGamma_xBig
  313. static $lg_frtbig = 2.25e76;
  314. static $pnt68 = 0.6796875;
  315. if ($x == self::$logGammaCacheX) {
  316. return self::$logGammaCacheResult;
  317. }
  318. $y = $x;
  319. if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) {
  320. if ($y <= EPS) {
  321. $res = -log(y);
  322. } elseif ($y <= 1.5) {
  323. // ---------------------
  324. // EPS .LT. X .LE. 1.5
  325. // ---------------------
  326. if ($y < $pnt68) {
  327. $corr = -log($y);
  328. $xm1 = $y;
  329. } else {
  330. $corr = 0.0;
  331. $xm1 = $y - 1.0;
  332. }
  333. if ($y <= 0.5 || $y >= $pnt68) {
  334. $xden = 1.0;
  335. $xnum = 0.0;
  336. for ($i = 0; $i < 8; ++$i) {
  337. $xnum = $xnum * $xm1 + $lg_p1[$i];
  338. $xden = $xden * $xm1 + $lg_q1[$i];
  339. }
  340. $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden));
  341. } else {
  342. $xm2 = $y - 1.0;
  343. $xden = 1.0;
  344. $xnum = 0.0;
  345. for ($i = 0; $i < 8; ++$i) {
  346. $xnum = $xnum * $xm2 + $lg_p2[$i];
  347. $xden = $xden * $xm2 + $lg_q2[$i];
  348. }
  349. $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
  350. }
  351. } elseif ($y <= 4.0) {
  352. // ---------------------
  353. // 1.5 .LT. X .LE. 4.0
  354. // ---------------------
  355. $xm2 = $y - 2.0;
  356. $xden = 1.0;
  357. $xnum = 0.0;
  358. for ($i = 0; $i < 8; ++$i) {
  359. $xnum = $xnum * $xm2 + $lg_p2[$i];
  360. $xden = $xden * $xm2 + $lg_q2[$i];
  361. }
  362. $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden));
  363. } elseif ($y <= 12.0) {
  364. // ----------------------
  365. // 4.0 .LT. X .LE. 12.0
  366. // ----------------------
  367. $xm4 = $y - 4.0;
  368. $xden = -1.0;
  369. $xnum = 0.0;
  370. for ($i = 0; $i < 8; ++$i) {
  371. $xnum = $xnum * $xm4 + $lg_p4[$i];
  372. $xden = $xden * $xm4 + $lg_q4[$i];
  373. }
  374. $res = $lg_d4 + $xm4 * ($xnum / $xden);
  375. } else {
  376. // ---------------------------------
  377. // Evaluate for argument .GE. 12.0
  378. // ---------------------------------
  379. $res = 0.0;
  380. if ($y <= $lg_frtbig) {
  381. $res = $lg_c[6];
  382. $ysq = $y * $y;
  383. for ($i = 0; $i < 6; ++$i) {
  384. $res = $res / $ysq + $lg_c[$i];
  385. }
  386. $res /= $y;
  387. $corr = log($y);
  388. $res = $res + log(SQRT2PI) - 0.5 * $corr;
  389. $res += $y * ($corr - 1.0);
  390. }
  391. }
  392. } else {
  393. // --------------------------
  394. // Return for bad arguments
  395. // --------------------------
  396. $res = MAX_VALUE;
  397. }
  398. // ------------------------------
  399. // Final adjustments and return
  400. // ------------------------------
  401. self::$logGammaCacheX = $x;
  402. self::$logGammaCacheResult = $res;
  403. return $res;
  404. }
  405. //
  406. // Private implementation of the incomplete Gamma function
  407. //
  408. private static function incompleteGamma($a, $x)
  409. {
  410. static $max = 32;
  411. $summer = 0;
  412. for ($n=0; $n<=$max; ++$n) {
  413. $divisor = $a;
  414. for ($i=1; $i<=$n; ++$i) {
  415. $divisor *= ($a + $i);
  416. }
  417. $summer += (pow($x, $n) / $divisor);
  418. }
  419. return pow($x, $a) * exp(0-$x) * $summer;
  420. }
  421. //
  422. // Private implementation of the Gamma function
  423. //
  424. private static function gamma($data)
  425. {
  426. if ($data == 0.0) {
  427. return 0;
  428. }
  429. static $p0 = 1.000000000190015;
  430. static $p = array(
  431. 1 => 76.18009172947146,
  432. 2 => -86.50532032941677,
  433. 3 => 24.01409824083091,
  434. 4 => -1.231739572450155,
  435. 5 => 1.208650973866179e-3,
  436. 6 => -5.395239384953e-6
  437. );
  438. $y = $x = $data;
  439. $tmp = $x + 5.5;
  440. $tmp -= ($x + 0.5) * log($tmp);
  441. $summer = $p0;
  442. for ($j=1; $j<=6; ++$j) {
  443. $summer += ($p[$j] / ++$y);
  444. }
  445. return exp(0 - $tmp + log(SQRT2PI * $summer / $x));
  446. }
  447. /***************************************************************************
  448. * inverse_ncdf.php
  449. * -------------------
  450. * begin : Friday, January 16, 2004
  451. * copyright : (C) 2004 Michael Nickerson
  452. * email : nickersonm@yahoo.com
  453. *
  454. ***************************************************************************/
  455. private static function inverseNcdf($p)
  456. {
  457. // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to
  458. // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as
  459. // a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html
  460. // I have not checked the accuracy of this implementation. Be aware that PHP
  461. // will truncate the coeficcients to 14 digits.
  462. // You have permission to use and distribute this function freely for
  463. // whatever purpose you want, but please show common courtesy and give credit
  464. // where credit is due.
  465. // Input paramater is $p - probability - where 0 < p < 1.
  466. // Coefficients in rational approximations
  467. static $a = array(
  468. 1 => -3.969683028665376e+01,
  469. 2 => 2.209460984245205e+02,
  470. 3 => -2.759285104469687e+02,
  471. 4 => 1.383577518672690e+02,
  472. 5 => -3.066479806614716e+01,
  473. 6 => 2.506628277459239e+00
  474. );
  475. static $b = array(
  476. 1 => -5.447609879822406e+01,
  477. 2 => 1.615858368580409e+02,
  478. 3 => -1.556989798598866e+02,
  479. 4 => 6.680131188771972e+01,
  480. 5 => -1.328068155288572e+01
  481. );
  482. static $c = array(
  483. 1 => -7.784894002430293e-03,
  484. 2 => -3.223964580411365e-01,
  485. 3 => -2.400758277161838e+00,
  486. 4 => -2.549732539343734e+00,
  487. 5 => 4.374664141464968e+00,
  488. 6 => 2.938163982698783e+00
  489. );
  490. static $d = array(
  491. 1 => 7.784695709041462e-03,
  492. 2 => 3.224671290700398e-01,
  493. 3 => 2.445134137142996e+00,
  494. 4 => 3.754408661907416e+00
  495. );
  496. // Define lower and upper region break-points.
  497. $p_low = 0.02425; //Use lower region approx. below this
  498. $p_high = 1 - $p_low; //Use upper region approx. above this
  499. if (0 < $p && $p < $p_low) {
  500. // Rational approximation for lower region.
  501. $q = sqrt(-2 * log($p));
  502. return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
  503. (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
  504. } elseif ($p_low <= $p && $p <= $p_high) {
  505. // Rational approximation for central region.
  506. $q = $p - 0.5;
  507. $r = $q * $q;
  508. return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q /
  509. ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1);
  510. } elseif ($p_high < $p && $p < 1) {
  511. // Rational approximation for upper region.
  512. $q = sqrt(-2 * log(1 - $p));
  513. return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) /
  514. (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1);
  515. }
  516. // If 0 < p < 1, return a null value
  517. return PHPExcel_Calculation_Functions::NULL();
  518. }
  519. private static function inverseNcdf2($prob)
  520. {
  521. // Approximation of inverse standard normal CDF developed by
  522. // B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58.
  523. $a1 = 2.50662823884;
  524. $a2 = -18.61500062529;
  525. $a3 = 41.39119773534;
  526. $a4 = -25.44106049637;
  527. $b1 = -8.4735109309;
  528. $b2 = 23.08336743743;
  529. $b3 = -21.06224101826;
  530. $b4 = 3.13082909833;
  531. $c1 = 0.337475482272615;
  532. $c2 = 0.976169019091719;
  533. $c3 = 0.160797971491821;
  534. $c4 = 2.76438810333863E-02;
  535. $c5 = 3.8405729373609E-03;
  536. $c6 = 3.951896511919E-04;
  537. $c7 = 3.21767881768E-05;
  538. $c8 = 2.888167364E-07;
  539. $c9 = 3.960315187E-07;
  540. $y = $prob - 0.5;
  541. if (abs($y) < 0.42) {
  542. $z = ($y * $y);
  543. $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1);
  544. } else {
  545. if ($y > 0) {
  546. $z = log(-log(1 - $prob));
  547. } else {
  548. $z = log(-log($prob));
  549. }
  550. $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9)))))));
  551. if ($y < 0) {
  552. $z = -$z;
  553. }
  554. }
  555. return $z;
  556. } // function inverseNcdf2()
  557. private static function inverseNcdf3($p)
  558. {
  559. // ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3.
  560. // Produces the normal deviate Z corresponding to a given lower
  561. // tail area of P; Z is accurate to about 1 part in 10**16.
  562. //
  563. // This is a PHP version of the original FORTRAN code that can
  564. // be found at http://lib.stat.cmu.edu/apstat/
  565. $split1 = 0.425;
  566. $split2 = 5;
  567. $const1 = 0.180625;
  568. $const2 = 1.6;
  569. // coefficients for p close to 0.5
  570. $a0 = 3.3871328727963666080;
  571. $a1 = 1.3314166789178437745E+2;
  572. $a2 = 1.9715909503065514427E+3;
  573. $a3 = 1.3731693765509461125E+4;
  574. $a4 = 4.5921953931549871457E+4;
  575. $a5 = 6.7265770927008700853E+4;
  576. $a6 = 3.3430575583588128105E+4;
  577. $a7 = 2.5090809287301226727E+3;
  578. $b1 = 4.2313330701600911252E+1;
  579. $b2 = 6.8718700749205790830E+2;
  580. $b3 = 5.3941960214247511077E+3;
  581. $b4 = 2.1213794301586595867E+4;
  582. $b5 = 3.9307895800092710610E+4;
  583. $b6 = 2.8729085735721942674E+4;
  584. $b7 = 5.2264952788528545610E+3;
  585. // coefficients for p not close to 0, 0.5 or 1.
  586. $c0 = 1.42343711074968357734;
  587. $c1 = 4.63033784615654529590;
  588. $c2 = 5.76949722146069140550;
  589. $c3 = 3.64784832476320460504;
  590. $c4 = 1.27045825245236838258;
  591. $c5 = 2.41780725177450611770E-1;
  592. $c6 = 2.27238449892691845833E-2;
  593. $c7 = 7.74545014278341407640E-4;
  594. $d1 = 2.05319162663775882187;
  595. $d2 = 1.67638483018380384940;
  596. $d3 = 6.89767334985100004550E-1;
  597. $d4 = 1.48103976427480074590E-1;
  598. $d5 = 1.51986665636164571966E-2;
  599. $d6 = 5.47593808499534494600E-4;
  600. $d7 = 1.05075007164441684324E-9;
  601. // coefficients for p near 0 or 1.
  602. $e0 = 6.65790464350110377720;
  603. $e1 = 5.46378491116411436990;
  604. $e2 = 1.78482653991729133580;
  605. $e3 = 2.96560571828504891230E-1;
  606. $e4 = 2.65321895265761230930E-2;
  607. $e5 = 1.24266094738807843860E-3;
  608. $e6 = 2.71155556874348757815E-5;
  609. $e7 = 2.01033439929228813265E-7;
  610. $f1 = 5.99832206555887937690E-1;
  611. $f2 = 1.36929880922735805310E-1;
  612. $f3 = 1.48753612908506148525E-2;
  613. $f4 = 7.86869131145613259100E-4;
  614. $f5 = 1.84631831751005468180E-5;
  615. $f6 = 1.42151175831644588870E-7;
  616. $f7 = 2.04426310338993978564E-15;
  617. $q = $p - 0.5;
  618. // computation for p close to 0.5
  619. if (abs($q) <= split1) {
  620. $R = $const1 - $q * $q;
  621. $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) /
  622. ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1);
  623. } else {
  624. if ($q < 0) {
  625. $R = $p;
  626. } else {
  627. $R = 1 - $p;
  628. }
  629. $R = pow(-log($R), 2);
  630. // computation for p not close to 0, 0.5 or 1.
  631. if ($R <= $split2) {
  632. $R = $R - $const2;
  633. $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) /
  634. ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1);
  635. } else {
  636. // computation for p near 0 or 1.
  637. $R = $R - $split2;
  638. $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) /
  639. ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1);
  640. }
  641. if ($q < 0) {
  642. $z = -$z;
  643. }
  644. }
  645. return $z;
  646. }
  647. /**
  648. * AVEDEV
  649. *
  650. * Returns the average of the absolute deviations of data points from their mean.
  651. * AVEDEV is a measure of the variability in a data set.
  652. *
  653. * Excel Function:
  654. * AVEDEV(value1[,value2[, ...]])
  655. *
  656. * @access public
  657. * @category Statistical Functions
  658. * @param mixed $arg,... Data values
  659. * @return float
  660. */
  661. public static function AVEDEV()
  662. {
  663. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  664. // Return value
  665. $returnValue = null;
  666. $aMean = self::AVERAGE($aArgs);
  667. if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
  668. $aCount = 0;
  669. foreach ($aArgs as $k => $arg) {
  670. if ((is_bool($arg)) &&
  671. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  672. $arg = (integer) $arg;
  673. }
  674. // Is it a numeric value?
  675. if ((is_numeric($arg)) && (!is_string($arg))) {
  676. if (is_null($returnValue)) {
  677. $returnValue = abs($arg - $aMean);
  678. } else {
  679. $returnValue += abs($arg - $aMean);
  680. }
  681. ++$aCount;
  682. }
  683. }
  684. // Return
  685. if ($aCount == 0) {
  686. return PHPExcel_Calculation_Functions::DIV0();
  687. }
  688. return $returnValue / $aCount;
  689. }
  690. return PHPExcel_Calculation_Functions::NaN();
  691. }
  692. /**
  693. * AVERAGE
  694. *
  695. * Returns the average (arithmetic mean) of the arguments
  696. *
  697. * Excel Function:
  698. * AVERAGE(value1[,value2[, ...]])
  699. *
  700. * @access public
  701. * @category Statistical Functions
  702. * @param mixed $arg,... Data values
  703. * @return float
  704. */
  705. public static function AVERAGE()
  706. {
  707. $returnValue = $aCount = 0;
  708. // Loop through arguments
  709. foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
  710. if ((is_bool($arg)) &&
  711. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  712. $arg = (integer) $arg;
  713. }
  714. // Is it a numeric value?
  715. if ((is_numeric($arg)) && (!is_string($arg))) {
  716. if (is_null($returnValue)) {
  717. $returnValue = $arg;
  718. } else {
  719. $returnValue += $arg;
  720. }
  721. ++$aCount;
  722. }
  723. }
  724. // Return
  725. if ($aCount > 0) {
  726. return $returnValue / $aCount;
  727. } else {
  728. return PHPExcel_Calculation_Functions::DIV0();
  729. }
  730. }
  731. /**
  732. * AVERAGEA
  733. *
  734. * Returns the average of its arguments, including numbers, text, and logical values
  735. *
  736. * Excel Function:
  737. * AVERAGEA(value1[,value2[, ...]])
  738. *
  739. * @access public
  740. * @category Statistical Functions
  741. * @param mixed $arg,... Data values
  742. * @return float
  743. */
  744. public static function AVERAGEA()
  745. {
  746. $returnValue = null;
  747. $aCount = 0;
  748. // Loop through arguments
  749. foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) {
  750. if ((is_bool($arg)) &&
  751. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  752. } else {
  753. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  754. if (is_bool($arg)) {
  755. $arg = (integer) $arg;
  756. } elseif (is_string($arg)) {
  757. $arg = 0;
  758. }
  759. if (is_null($returnValue)) {
  760. $returnValue = $arg;
  761. } else {
  762. $returnValue += $arg;
  763. }
  764. ++$aCount;
  765. }
  766. }
  767. }
  768. if ($aCount > 0) {
  769. return $returnValue / $aCount;
  770. } else {
  771. return PHPExcel_Calculation_Functions::DIV0();
  772. }
  773. }
  774. /**
  775. * AVERAGEIF
  776. *
  777. * Returns the average value from a range of cells that contain numbers within the list of arguments
  778. *
  779. * Excel Function:
  780. * AVERAGEIF(value1[,value2[, ...]],condition)
  781. *
  782. * @access public
  783. * @category Mathematical and Trigonometric Functions
  784. * @param mixed $arg,... Data values
  785. * @param string $condition The criteria that defines which cells will be checked.
  786. * @param mixed[] $averageArgs Data values
  787. * @return float
  788. */
  789. public static function AVERAGEIF($aArgs, $condition, $averageArgs = array())
  790. {
  791. $returnValue = 0;
  792. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  793. $averageArgs = PHPExcel_Calculation_Functions::flattenArray($averageArgs);
  794. if (empty($averageArgs)) {
  795. $averageArgs = $aArgs;
  796. }
  797. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  798. // Loop through arguments
  799. $aCount = 0;
  800. foreach ($aArgs as $key => $arg) {
  801. if (!is_numeric($arg)) {
  802. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  803. }
  804. $testCondition = '='.$arg.$condition;
  805. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  806. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  807. $returnValue += $arg;
  808. ++$aCount;
  809. }
  810. }
  811. }
  812. if ($aCount > 0) {
  813. return $returnValue / $aCount;
  814. }
  815. return PHPExcel_Calculation_Functions::DIV0();
  816. }
  817. /**
  818. * BETADIST
  819. *
  820. * Returns the beta distribution.
  821. *
  822. * @param float $value Value at which you want to evaluate the distribution
  823. * @param float $alpha Parameter to the distribution
  824. * @param float $beta Parameter to the distribution
  825. * @param boolean $cumulative
  826. * @return float
  827. *
  828. */
  829. public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1)
  830. {
  831. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  832. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  833. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  834. $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
  835. $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
  836. if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
  837. if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) {
  838. return PHPExcel_Calculation_Functions::NaN();
  839. }
  840. if ($rMin > $rMax) {
  841. $tmp = $rMin;
  842. $rMin = $rMax;
  843. $rMax = $tmp;
  844. }
  845. $value -= $rMin;
  846. $value /= ($rMax - $rMin);
  847. return self::incompleteBeta($value, $alpha, $beta);
  848. }
  849. return PHPExcel_Calculation_Functions::VALUE();
  850. }
  851. /**
  852. * BETAINV
  853. *
  854. * Returns the inverse of the beta distribution.
  855. *
  856. * @param float $probability Probability at which you want to evaluate the distribution
  857. * @param float $alpha Parameter to the distribution
  858. * @param float $beta Parameter to the distribution
  859. * @param float $rMin Minimum value
  860. * @param float $rMax Maximum value
  861. * @param boolean $cumulative
  862. * @return float
  863. *
  864. */
  865. public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1)
  866. {
  867. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  868. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  869. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  870. $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin);
  871. $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax);
  872. if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) {
  873. if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) {
  874. return PHPExcel_Calculation_Functions::NaN();
  875. }
  876. if ($rMin > $rMax) {
  877. $tmp = $rMin;
  878. $rMin = $rMax;
  879. $rMax = $tmp;
  880. }
  881. $a = 0;
  882. $b = 2;
  883. $i = 0;
  884. while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  885. $guess = ($a + $b) / 2;
  886. $result = self::BETADIST($guess, $alpha, $beta);
  887. if (($result == $probability) || ($result == 0)) {
  888. $b = $a;
  889. } elseif ($result > $probability) {
  890. $b = $guess;
  891. } else {
  892. $a = $guess;
  893. }
  894. }
  895. if ($i == MAX_ITERATIONS) {
  896. return PHPExcel_Calculation_Functions::NA();
  897. }
  898. return round($rMin + $guess * ($rMax - $rMin), 12);
  899. }
  900. return PHPExcel_Calculation_Functions::VALUE();
  901. }
  902. /**
  903. * BINOMDIST
  904. *
  905. * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with
  906. * a fixed number of tests or trials, when the outcomes of any trial are only success or failure,
  907. * when trials are independent, and when the probability of success is constant throughout the
  908. * experiment. For example, BINOMDIST can calculate the probability that two of the next three
  909. * babies born are male.
  910. *
  911. * @param float $value Number of successes in trials
  912. * @param float $trials Number of trials
  913. * @param float $probability Probability of success on each trial
  914. * @param boolean $cumulative
  915. * @return float
  916. *
  917. * @todo Cumulative distribution function
  918. *
  919. */
  920. public static function BINOMDIST($value, $trials, $probability, $cumulative)
  921. {
  922. $value = floor(PHPExcel_Calculation_Functions::flattenSingleValue($value));
  923. $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
  924. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  925. if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) {
  926. if (($value < 0) || ($value > $trials)) {
  927. return PHPExcel_Calculation_Functions::NaN();
  928. }
  929. if (($probability < 0) || ($probability > 1)) {
  930. return PHPExcel_Calculation_Functions::NaN();
  931. }
  932. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  933. if ($cumulative) {
  934. $summer = 0;
  935. for ($i = 0; $i <= $value; ++$i) {
  936. $summer += PHPExcel_Calculation_MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i);
  937. }
  938. return $summer;
  939. } else {
  940. return PHPExcel_Calculation_MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value) ;
  941. }
  942. }
  943. }
  944. return PHPExcel_Calculation_Functions::VALUE();
  945. }
  946. /**
  947. * CHIDIST
  948. *
  949. * Returns the one-tailed probability of the chi-squared distribution.
  950. *
  951. * @param float $value Value for the function
  952. * @param float $degrees degrees of freedom
  953. * @return float
  954. */
  955. public static function CHIDIST($value, $degrees)
  956. {
  957. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  958. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  959. if ((is_numeric($value)) && (is_numeric($degrees))) {
  960. if ($degrees < 1) {
  961. return PHPExcel_Calculation_Functions::NaN();
  962. }
  963. if ($value < 0) {
  964. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  965. return 1;
  966. }
  967. return PHPExcel_Calculation_Functions::NaN();
  968. }
  969. return 1 - (self::incompleteGamma($degrees/2, $value/2) / self::gamma($degrees/2));
  970. }
  971. return PHPExcel_Calculation_Functions::VALUE();
  972. }
  973. /**
  974. * CHIINV
  975. *
  976. * Returns the one-tailed probability of the chi-squared distribution.
  977. *
  978. * @param float $probability Probability for the function
  979. * @param float $degrees degrees of freedom
  980. * @return float
  981. */
  982. public static function CHIINV($probability, $degrees)
  983. {
  984. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  985. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  986. if ((is_numeric($probability)) && (is_numeric($degrees))) {
  987. $xLo = 100;
  988. $xHi = 0;
  989. $x = $xNew = 1;
  990. $dx = 1;
  991. $i = 0;
  992. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  993. // Apply Newton-Raphson step
  994. $result = self::CHIDIST($x, $degrees);
  995. $error = $result - $probability;
  996. if ($error == 0.0) {
  997. $dx = 0;
  998. } elseif ($error < 0.0) {
  999. $xLo = $x;
  1000. } else {
  1001. $xHi = $x;
  1002. }
  1003. // Avoid division by zero
  1004. if ($result != 0.0) {
  1005. $dx = $error / $result;
  1006. $xNew = $x - $dx;
  1007. }
  1008. // If the NR fails to converge (which for example may be the
  1009. // case if the initial guess is too rough) we apply a bisection
  1010. // step to determine a more narrow interval around the root.
  1011. if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
  1012. $xNew = ($xLo + $xHi) / 2;
  1013. $dx = $xNew - $x;
  1014. }
  1015. $x = $xNew;
  1016. }
  1017. if ($i == MAX_ITERATIONS) {
  1018. return PHPExcel_Calculation_Functions::NA();
  1019. }
  1020. return round($x, 12);
  1021. }
  1022. return PHPExcel_Calculation_Functions::VALUE();
  1023. }
  1024. /**
  1025. * CONFIDENCE
  1026. *
  1027. * Returns the confidence interval for a population mean
  1028. *
  1029. * @param float $alpha
  1030. * @param float $stdDev Standard Deviation
  1031. * @param float $size
  1032. * @return float
  1033. *
  1034. */
  1035. public static function CONFIDENCE($alpha, $stdDev, $size)
  1036. {
  1037. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1038. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1039. $size = floor(PHPExcel_Calculation_Functions::flattenSingleValue($size));
  1040. if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) {
  1041. if (($alpha <= 0) || ($alpha >= 1)) {
  1042. return PHPExcel_Calculation_Functions::NaN();
  1043. }
  1044. if (($stdDev <= 0) || ($size < 1)) {
  1045. return PHPExcel_Calculation_Functions::NaN();
  1046. }
  1047. return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size);
  1048. }
  1049. return PHPExcel_Calculation_Functions::VALUE();
  1050. }
  1051. /**
  1052. * CORREL
  1053. *
  1054. * Returns covariance, the average of the products of deviations for each data point pair.
  1055. *
  1056. * @param array of mixed Data Series Y
  1057. * @param array of mixed Data Series X
  1058. * @return float
  1059. */
  1060. public static function CORREL($yValues, $xValues = null)
  1061. {
  1062. if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) {
  1063. return PHPExcel_Calculation_Functions::VALUE();
  1064. }
  1065. if (!self::checkTrendArrays($yValues, $xValues)) {
  1066. return PHPExcel_Calculation_Functions::VALUE();
  1067. }
  1068. $yValueCount = count($yValues);
  1069. $xValueCount = count($xValues);
  1070. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1071. return PHPExcel_Calculation_Functions::NA();
  1072. } elseif ($yValueCount == 1) {
  1073. return PHPExcel_Calculation_Functions::DIV0();
  1074. }
  1075. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1076. return $bestFitLinear->getCorrelation();
  1077. }
  1078. /**
  1079. * COUNT
  1080. *
  1081. * Counts the number of cells that contain numbers within the list of arguments
  1082. *
  1083. * Excel Function:
  1084. * COUNT(value1[,value2[, ...]])
  1085. *
  1086. * @access public
  1087. * @category Statistical Functions
  1088. * @param mixed $arg,... Data values
  1089. * @return int
  1090. */
  1091. public static function COUNT()
  1092. {
  1093. $returnValue = 0;
  1094. // Loop through arguments
  1095. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1096. foreach ($aArgs as $k => $arg) {
  1097. if ((is_bool($arg)) &&
  1098. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  1099. $arg = (integer) $arg;
  1100. }
  1101. // Is it a numeric value?
  1102. if ((is_numeric($arg)) && (!is_string($arg))) {
  1103. ++$returnValue;
  1104. }
  1105. }
  1106. return $returnValue;
  1107. }
  1108. /**
  1109. * COUNTA
  1110. *
  1111. * Counts the number of cells that are not empty within the list of arguments
  1112. *
  1113. * Excel Function:
  1114. * COUNTA(value1[,value2[, ...]])
  1115. *
  1116. * @access public
  1117. * @category Statistical Functions
  1118. * @param mixed $arg,... Data values
  1119. * @return int
  1120. */
  1121. public static function COUNTA()
  1122. {
  1123. $returnValue = 0;
  1124. // Loop through arguments
  1125. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1126. foreach ($aArgs as $arg) {
  1127. // Is it a numeric, boolean or string value?
  1128. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  1129. ++$returnValue;
  1130. }
  1131. }
  1132. return $returnValue;
  1133. }
  1134. /**
  1135. * COUNTBLANK
  1136. *
  1137. * Counts the number of empty cells within the list of arguments
  1138. *
  1139. * Excel Function:
  1140. * COUNTBLANK(value1[,value2[, ...]])
  1141. *
  1142. * @access public
  1143. * @category Statistical Functions
  1144. * @param mixed $arg,... Data values
  1145. * @return int
  1146. */
  1147. public static function COUNTBLANK()
  1148. {
  1149. $returnValue = 0;
  1150. // Loop through arguments
  1151. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1152. foreach ($aArgs as $arg) {
  1153. // Is it a blank cell?
  1154. if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
  1155. ++$returnValue;
  1156. }
  1157. }
  1158. return $returnValue;
  1159. }
  1160. /**
  1161. * COUNTIF
  1162. *
  1163. * Counts the number of cells that contain numbers within the list of arguments
  1164. *
  1165. * Excel Function:
  1166. * COUNTIF(value1[,value2[, ...]],condition)
  1167. *
  1168. * @access public
  1169. * @category Statistical Functions
  1170. * @param mixed $arg,... Data values
  1171. * @param string $condition The criteria that defines which cells will be counted.
  1172. * @return int
  1173. */
  1174. public static function COUNTIF($aArgs, $condition)
  1175. {
  1176. $returnValue = 0;
  1177. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  1178. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  1179. // Loop through arguments
  1180. foreach ($aArgs as $arg) {
  1181. if (!is_numeric($arg)) {
  1182. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  1183. }
  1184. $testCondition = '='.$arg.$condition;
  1185. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  1186. // Is it a value within our criteria
  1187. ++$returnValue;
  1188. }
  1189. }
  1190. return $returnValue;
  1191. }
  1192. /**
  1193. * COVAR
  1194. *
  1195. * Returns covariance, the average of the products of deviations for each data point pair.
  1196. *
  1197. * @param array of mixed Data Series Y
  1198. * @param array of mixed Data Series X
  1199. * @return float
  1200. */
  1201. public static function COVAR($yValues, $xValues)
  1202. {
  1203. if (!self::checkTrendArrays($yValues, $xValues)) {
  1204. return PHPExcel_Calculation_Functions::VALUE();
  1205. }
  1206. $yValueCount = count($yValues);
  1207. $xValueCount = count($xValues);
  1208. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1209. return PHPExcel_Calculation_Functions::NA();
  1210. } elseif ($yValueCount == 1) {
  1211. return PHPExcel_Calculation_Functions::DIV0();
  1212. }
  1213. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1214. return $bestFitLinear->getCovariance();
  1215. }
  1216. /**
  1217. * CRITBINOM
  1218. *
  1219. * Returns the smallest value for which the cumulative binomial distribution is greater
  1220. * than or equal to a criterion value
  1221. *
  1222. * See http://support.microsoft.com/kb/828117/ for details of the algorithm used
  1223. *
  1224. * @param float $trials number of Bernoulli trials
  1225. * @param float $probability probability of a success on each trial
  1226. * @param float $alpha criterion value
  1227. * @return int
  1228. *
  1229. * @todo Warning. This implementation differs from the algorithm detailed on the MS
  1230. * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess
  1231. * This eliminates a potential endless loop error, but may have an adverse affect on the
  1232. * accuracy of the function (although all my tests have so far returned correct results).
  1233. *
  1234. */
  1235. public static function CRITBINOM($trials, $probability, $alpha)
  1236. {
  1237. $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials));
  1238. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1239. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1240. if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) {
  1241. if ($trials < 0) {
  1242. return PHPExcel_Calculation_Functions::NaN();
  1243. } elseif (($probability < 0) || ($probability > 1)) {
  1244. return PHPExcel_Calculation_Functions::NaN();
  1245. } elseif (($alpha < 0) || ($alpha > 1)) {
  1246. return PHPExcel_Calculation_Functions::NaN();
  1247. } elseif ($alpha <= 0.5) {
  1248. $t = sqrt(log(1 / ($alpha * $alpha)));
  1249. $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t));
  1250. } else {
  1251. $t = sqrt(log(1 / pow(1 - $alpha, 2)));
  1252. $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t);
  1253. }
  1254. $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability)));
  1255. if ($Guess < 0) {
  1256. $Guess = 0;
  1257. } elseif ($Guess > $trials) {
  1258. $Guess = $trials;
  1259. }
  1260. $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0;
  1261. $EssentiallyZero = 10e-12;
  1262. $m = floor($trials * $probability);
  1263. ++$TotalUnscaledProbability;
  1264. if ($m == $Guess) {
  1265. ++$UnscaledPGuess;
  1266. }
  1267. if ($m <= $Guess) {
  1268. ++$UnscaledCumPGuess;
  1269. }
  1270. $PreviousValue = 1;
  1271. $Done = false;
  1272. $k = $m + 1;
  1273. while ((!$Done) && ($k <= $trials)) {
  1274. $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability));
  1275. $TotalUnscaledProbability += $CurrentValue;
  1276. if ($k == $Guess) {
  1277. $UnscaledPGuess += $CurrentValue;
  1278. }
  1279. if ($k <= $Guess) {
  1280. $UnscaledCumPGuess += $CurrentValue;
  1281. }
  1282. if ($CurrentValue <= $EssentiallyZero) {
  1283. $Done = true;
  1284. }
  1285. $PreviousValue = $CurrentValue;
  1286. ++$k;
  1287. }
  1288. $PreviousValue = 1;
  1289. $Done = false;
  1290. $k = $m - 1;
  1291. while ((!$Done) && ($k >= 0)) {
  1292. $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability);
  1293. $TotalUnscaledProbability += $CurrentValue;
  1294. if ($k == $Guess) {
  1295. $UnscaledPGuess += $CurrentValue;
  1296. }
  1297. if ($k <= $Guess) {
  1298. $UnscaledCumPGuess += $CurrentValue;
  1299. }
  1300. if ($CurrentValue <= $EssentiallyZero) {
  1301. $Done = true;
  1302. }
  1303. $PreviousValue = $CurrentValue;
  1304. --$k;
  1305. }
  1306. $PGuess = $UnscaledPGuess / $TotalUnscaledProbability;
  1307. $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability;
  1308. // $CumPGuessMinus1 = $CumPGuess - $PGuess;
  1309. $CumPGuessMinus1 = $CumPGuess - 1;
  1310. while (true) {
  1311. if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) {
  1312. return $Guess;
  1313. } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) {
  1314. $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability);
  1315. $CumPGuessMinus1 = $CumPGuess;
  1316. $CumPGuess = $CumPGuess + $PGuessPlus1;
  1317. $PGuess = $PGuessPlus1;
  1318. ++$Guess;
  1319. } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) {
  1320. $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability;
  1321. $CumPGuess = $CumPGuessMinus1;
  1322. $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess;
  1323. $PGuess = $PGuessMinus1;
  1324. --$Guess;
  1325. }
  1326. }
  1327. }
  1328. return PHPExcel_Calculation_Functions::VALUE();
  1329. }
  1330. /**
  1331. * DEVSQ
  1332. *
  1333. * Returns the sum of squares of deviations of data points from their sample mean.
  1334. *
  1335. * Excel Function:
  1336. * DEVSQ(value1[,value2[, ...]])
  1337. *
  1338. * @access public
  1339. * @category Statistical Functions
  1340. * @param mixed $arg,... Data values
  1341. * @return float
  1342. */
  1343. public static function DEVSQ()
  1344. {
  1345. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1346. // Return value
  1347. $returnValue = null;
  1348. $aMean = self::AVERAGE($aArgs);
  1349. if ($aMean != PHPExcel_Calculation_Functions::DIV0()) {
  1350. $aCount = -1;
  1351. foreach ($aArgs as $k => $arg) {
  1352. // Is it a numeric value?
  1353. if ((is_bool($arg)) &&
  1354. ((!PHPExcel_Calculation_Functions::isCellValue($k)) ||
  1355. (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  1356. $arg = (integer) $arg;
  1357. }
  1358. if ((is_numeric($arg)) && (!is_string($arg))) {
  1359. if (is_null($returnValue)) {
  1360. $returnValue = pow(($arg - $aMean), 2);
  1361. } else {
  1362. $returnValue += pow(($arg - $aMean), 2);
  1363. }
  1364. ++$aCount;
  1365. }
  1366. }
  1367. // Return
  1368. if (is_null($returnValue)) {
  1369. return PHPExcel_Calculation_Functions::NaN();
  1370. } else {
  1371. return $returnValue;
  1372. }
  1373. }
  1374. return self::NA();
  1375. }
  1376. /**
  1377. * EXPONDIST
  1378. *
  1379. * Returns the exponential distribution. Use EXPONDIST to model the time between events,
  1380. * such as how long an automated bank teller takes to deliver cash. For example, you can
  1381. * use EXPONDIST to determine the probability that the process takes at most 1 minute.
  1382. *
  1383. * @param float $value Value of the function
  1384. * @param float $lambda The parameter value
  1385. * @param boolean $cumulative
  1386. * @return float
  1387. */
  1388. public static function EXPONDIST($value, $lambda, $cumulative)
  1389. {
  1390. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1391. $lambda = PHPExcel_Calculation_Functions::flattenSingleValue($lambda);
  1392. $cumulative = PHPExcel_Calculation_Functions::flattenSingleValue($cumulative);
  1393. if ((is_numeric($value)) && (is_numeric($lambda))) {
  1394. if (($value < 0) || ($lambda < 0)) {
  1395. return PHPExcel_Calculation_Functions::NaN();
  1396. }
  1397. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  1398. if ($cumulative) {
  1399. return 1 - exp(0-$value*$lambda);
  1400. } else {
  1401. return $lambda * exp(0-$value*$lambda);
  1402. }
  1403. }
  1404. }
  1405. return PHPExcel_Calculation_Functions::VALUE();
  1406. }
  1407. /**
  1408. * FISHER
  1409. *
  1410. * Returns the Fisher transformation at x. This transformation produces a function that
  1411. * is normally distributed rather than skewed. Use this function to perform hypothesis
  1412. * testing on the correlation coefficient.
  1413. *
  1414. * @param float $value
  1415. * @return float
  1416. */
  1417. public static function FISHER($value)
  1418. {
  1419. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1420. if (is_numeric($value)) {
  1421. if (($value <= -1) || ($value >= 1)) {
  1422. return PHPExcel_Calculation_Functions::NaN();
  1423. }
  1424. return 0.5 * log((1+$value)/(1-$value));
  1425. }
  1426. return PHPExcel_Calculation_Functions::VALUE();
  1427. }
  1428. /**
  1429. * FISHERINV
  1430. *
  1431. * Returns the inverse of the Fisher transformation. Use this transformation when
  1432. * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then
  1433. * FISHERINV(y) = x.
  1434. *
  1435. * @param float $value
  1436. * @return float
  1437. */
  1438. public static function FISHERINV($value)
  1439. {
  1440. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1441. if (is_numeric($value)) {
  1442. return (exp(2 * $value) - 1) / (exp(2 * $value) + 1);
  1443. }
  1444. return PHPExcel_Calculation_Functions::VALUE();
  1445. }
  1446. /**
  1447. * FORECAST
  1448. *
  1449. * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
  1450. *
  1451. * @param float Value of X for which we want to find Y
  1452. * @param array of mixed Data Series Y
  1453. * @param array of mixed Data Series X
  1454. * @return float
  1455. */
  1456. public static function FORECAST($xValue, $yValues, $xValues)
  1457. {
  1458. $xValue = PHPExcel_Calculation_Functions::flattenSingleValue($xValue);
  1459. if (!is_numeric($xValue)) {
  1460. return PHPExcel_Calculation_Functions::VALUE();
  1461. } elseif (!self::checkTrendArrays($yValues, $xValues)) {
  1462. return PHPExcel_Calculation_Functions::VALUE();
  1463. }
  1464. $yValueCount = count($yValues);
  1465. $xValueCount = count($xValues);
  1466. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1467. return PHPExcel_Calculation_Functions::NA();
  1468. } elseif ($yValueCount == 1) {
  1469. return PHPExcel_Calculation_Functions::DIV0();
  1470. }
  1471. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1472. return $bestFitLinear->getValueOfYForX($xValue);
  1473. }
  1474. /**
  1475. * GAMMADIST
  1476. *
  1477. * Returns the gamma distribution.
  1478. *
  1479. * @param float $value Value at which you want to evaluate the distribution
  1480. * @param float $a Parameter to the distribution
  1481. * @param float $b Parameter to the distribution
  1482. * @param boolean $cumulative
  1483. * @return float
  1484. *
  1485. */
  1486. public static function GAMMADIST($value, $a, $b, $cumulative)
  1487. {
  1488. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1489. $a = PHPExcel_Calculation_Functions::flattenSingleValue($a);
  1490. $b = PHPExcel_Calculation_Functions::flattenSingleValue($b);
  1491. if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) {
  1492. if (($value < 0) || ($a <= 0) || ($b <= 0)) {
  1493. return PHPExcel_Calculation_Functions::NaN();
  1494. }
  1495. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  1496. if ($cumulative) {
  1497. return self::incompleteGamma($a, $value / $b) / self::gamma($a);
  1498. } else {
  1499. return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a-1) * exp(0-($value / $b));
  1500. }
  1501. }
  1502. }
  1503. return PHPExcel_Calculation_Functions::VALUE();
  1504. }
  1505. /**
  1506. * GAMMAINV
  1507. *
  1508. * Returns the inverse of the beta distribution.
  1509. *
  1510. * @param float $probability Probability at which you want to evaluate the distribution
  1511. * @param float $alpha Parameter to the distribution
  1512. * @param float $beta Parameter to the distribution
  1513. * @return float
  1514. *
  1515. */
  1516. public static function GAMMAINV($probability, $alpha, $beta)
  1517. {
  1518. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1519. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  1520. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  1521. if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) {
  1522. if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) {
  1523. return PHPExcel_Calculation_Functions::NaN();
  1524. }
  1525. $xLo = 0;
  1526. $xHi = $alpha * $beta * 5;
  1527. $x = $xNew = 1;
  1528. $error = $pdf = 0;
  1529. $dx = 1024;
  1530. $i = 0;
  1531. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  1532. // Apply Newton-Raphson step
  1533. $error = self::GAMMADIST($x, $alpha, $beta, true) - $probability;
  1534. if ($error < 0.0) {
  1535. $xLo = $x;
  1536. } else {
  1537. $xHi = $x;
  1538. }
  1539. $pdf = self::GAMMADIST($x, $alpha, $beta, false);
  1540. // Avoid division by zero
  1541. if ($pdf != 0.0) {
  1542. $dx = $error / $pdf;
  1543. $xNew = $x - $dx;
  1544. }
  1545. // If the NR fails to converge (which for example may be the
  1546. // case if the initial guess is too rough) we apply a bisection
  1547. // step to determine a more narrow interval around the root.
  1548. if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) {
  1549. $xNew = ($xLo + $xHi) / 2;
  1550. $dx = $xNew - $x;
  1551. }
  1552. $x = $xNew;
  1553. }
  1554. if ($i == MAX_ITERATIONS) {
  1555. return PHPExcel_Calculation_Functions::NA();
  1556. }
  1557. return $x;
  1558. }
  1559. return PHPExcel_Calculation_Functions::VALUE();
  1560. }
  1561. /**
  1562. * GAMMALN
  1563. *
  1564. * Returns the natural logarithm of the gamma function.
  1565. *
  1566. * @param float $value
  1567. * @return float
  1568. */
  1569. public static function GAMMALN($value)
  1570. {
  1571. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1572. if (is_numeric($value)) {
  1573. if ($value <= 0) {
  1574. return PHPExcel_Calculation_Functions::NaN();
  1575. }
  1576. return log(self::gamma($value));
  1577. }
  1578. return PHPExcel_Calculation_Functions::VALUE();
  1579. }
  1580. /**
  1581. * GEOMEAN
  1582. *
  1583. * Returns the geometric mean of an array or range of positive data. For example, you
  1584. * can use GEOMEAN to calculate average growth rate given compound interest with
  1585. * variable rates.
  1586. *
  1587. * Excel Function:
  1588. * GEOMEAN(value1[,value2[, ...]])
  1589. *
  1590. * @access public
  1591. * @category Statistical Functions
  1592. * @param mixed $arg,... Data values
  1593. * @return float
  1594. */
  1595. public static function GEOMEAN()
  1596. {
  1597. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1598. $aMean = PHPExcel_Calculation_MathTrig::PRODUCT($aArgs);
  1599. if (is_numeric($aMean) && ($aMean > 0)) {
  1600. $aCount = self::COUNT($aArgs) ;
  1601. if (self::MIN($aArgs) > 0) {
  1602. return pow($aMean, (1 / $aCount));
  1603. }
  1604. }
  1605. return PHPExcel_Calculation_Functions::NaN();
  1606. }
  1607. /**
  1608. * GROWTH
  1609. *
  1610. * Returns values along a predicted emponential trend
  1611. *
  1612. * @param array of mixed Data Series Y
  1613. * @param array of mixed Data Series X
  1614. * @param array of mixed Values of X for which we want to find Y
  1615. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1616. * @return array of float
  1617. */
  1618. public static function GROWTH($yValues, $xValues = array(), $newValues = array(), $const = true)
  1619. {
  1620. $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
  1621. $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
  1622. $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
  1623. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1624. $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
  1625. if (empty($newValues)) {
  1626. $newValues = $bestFitExponential->getXValues();
  1627. }
  1628. $returnArray = array();
  1629. foreach ($newValues as $xValue) {
  1630. $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
  1631. }
  1632. return $returnArray;
  1633. }
  1634. /**
  1635. * HARMEAN
  1636. *
  1637. * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
  1638. * arithmetic mean of reciprocals.
  1639. *
  1640. * Excel Function:
  1641. * HARMEAN(value1[,value2[, ...]])
  1642. *
  1643. * @access public
  1644. * @category Statistical Functions
  1645. * @param mixed $arg,... Data values
  1646. * @return float
  1647. */
  1648. public static function HARMEAN()
  1649. {
  1650. // Return value
  1651. $returnValue = PHPExcel_Calculation_Functions::NA();
  1652. // Loop through arguments
  1653. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1654. if (self::MIN($aArgs) < 0) {
  1655. return PHPExcel_Calculation_Functions::NaN();
  1656. }
  1657. $aCount = 0;
  1658. foreach ($aArgs as $arg) {
  1659. // Is it a numeric value?
  1660. if ((is_numeric($arg)) && (!is_string($arg))) {
  1661. if ($arg <= 0) {
  1662. return PHPExcel_Calculation_Functions::NaN();
  1663. }
  1664. if (is_null($returnValue)) {
  1665. $returnValue = (1 / $arg);
  1666. } else {
  1667. $returnValue += (1 / $arg);
  1668. }
  1669. ++$aCount;
  1670. }
  1671. }
  1672. // Return
  1673. if ($aCount > 0) {
  1674. return 1 / ($returnValue / $aCount);
  1675. } else {
  1676. return $returnValue;
  1677. }
  1678. }
  1679. /**
  1680. * HYPGEOMDIST
  1681. *
  1682. * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of
  1683. * sample successes, given the sample size, population successes, and population size.
  1684. *
  1685. * @param float $sampleSuccesses Number of successes in the sample
  1686. * @param float $sampleNumber Size of the sample
  1687. * @param float $populationSuccesses Number of successes in the population
  1688. * @param float $populationNumber Population size
  1689. * @return float
  1690. *
  1691. */
  1692. public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber)
  1693. {
  1694. $sampleSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleSuccesses));
  1695. $sampleNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleNumber));
  1696. $populationSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationSuccesses));
  1697. $populationNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationNumber));
  1698. if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) {
  1699. if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) {
  1700. return PHPExcel_Calculation_Functions::NaN();
  1701. }
  1702. if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) {
  1703. return PHPExcel_Calculation_Functions::NaN();
  1704. }
  1705. if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) {
  1706. return PHPExcel_Calculation_Functions::NaN();
  1707. }
  1708. return PHPExcel_Calculation_MathTrig::COMBIN($populationSuccesses, $sampleSuccesses) *
  1709. PHPExcel_Calculation_MathTrig::COMBIN($populationNumber - $populationSuccesses, $sampleNumber - $sampleSuccesses) /
  1710. PHPExcel_Calculation_MathTrig::COMBIN($populationNumber, $sampleNumber);
  1711. }
  1712. return PHPExcel_Calculation_Functions::VALUE();
  1713. }
  1714. /**
  1715. * INTERCEPT
  1716. *
  1717. * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
  1718. *
  1719. * @param array of mixed Data Series Y
  1720. * @param array of mixed Data Series X
  1721. * @return float
  1722. */
  1723. public static function INTERCEPT($yValues, $xValues)
  1724. {
  1725. if (!self::checkTrendArrays($yValues, $xValues)) {
  1726. return PHPExcel_Calculation_Functions::VALUE();
  1727. }
  1728. $yValueCount = count($yValues);
  1729. $xValueCount = count($xValues);
  1730. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1731. return PHPExcel_Calculation_Functions::NA();
  1732. } elseif ($yValueCount == 1) {
  1733. return PHPExcel_Calculation_Functions::DIV0();
  1734. }
  1735. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  1736. return $bestFitLinear->getIntersect();
  1737. }
  1738. /**
  1739. * KURT
  1740. *
  1741. * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
  1742. * or flatness of a distribution compared with the normal distribution. Positive
  1743. * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
  1744. * relatively flat distribution.
  1745. *
  1746. * @param array Data Series
  1747. * @return float
  1748. */
  1749. public static function KURT()
  1750. {
  1751. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  1752. $mean = self::AVERAGE($aArgs);
  1753. $stdDev = self::STDEV($aArgs);
  1754. if ($stdDev > 0) {
  1755. $count = $summer = 0;
  1756. // Loop through arguments
  1757. foreach ($aArgs as $k => $arg) {
  1758. if ((is_bool($arg)) &&
  1759. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  1760. } else {
  1761. // Is it a numeric value?
  1762. if ((is_numeric($arg)) && (!is_string($arg))) {
  1763. $summer += pow((($arg - $mean) / $stdDev), 4);
  1764. ++$count;
  1765. }
  1766. }
  1767. }
  1768. // Return
  1769. if ($count > 3) {
  1770. return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1, 2) / (($count-2) * ($count-3)));
  1771. }
  1772. }
  1773. return PHPExcel_Calculation_Functions::DIV0();
  1774. }
  1775. /**
  1776. * LARGE
  1777. *
  1778. * Returns the nth largest value in a data set. You can use this function to
  1779. * select a value based on its relative standing.
  1780. *
  1781. * Excel Function:
  1782. * LARGE(value1[,value2[, ...]],entry)
  1783. *
  1784. * @access public
  1785. * @category Statistical Functions
  1786. * @param mixed $arg,... Data values
  1787. * @param int $entry Position (ordered from the largest) in the array or range of data to return
  1788. * @return float
  1789. *
  1790. */
  1791. public static function LARGE()
  1792. {
  1793. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1794. // Calculate
  1795. $entry = floor(array_pop($aArgs));
  1796. if ((is_numeric($entry)) && (!is_string($entry))) {
  1797. $mArgs = array();
  1798. foreach ($aArgs as $arg) {
  1799. // Is it a numeric value?
  1800. if ((is_numeric($arg)) && (!is_string($arg))) {
  1801. $mArgs[] = $arg;
  1802. }
  1803. }
  1804. $count = self::COUNT($mArgs);
  1805. $entry = floor(--$entry);
  1806. if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
  1807. return PHPExcel_Calculation_Functions::NaN();
  1808. }
  1809. rsort($mArgs);
  1810. return $mArgs[$entry];
  1811. }
  1812. return PHPExcel_Calculation_Functions::VALUE();
  1813. }
  1814. /**
  1815. * LINEST
  1816. *
  1817. * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
  1818. * and then returns an array that describes the line.
  1819. *
  1820. * @param array of mixed Data Series Y
  1821. * @param array of mixed Data Series X
  1822. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1823. * @param boolean A logical value specifying whether to return additional regression statistics.
  1824. * @return array
  1825. */
  1826. public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
  1827. {
  1828. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1829. $stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
  1830. if (is_null($xValues)) {
  1831. $xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
  1832. }
  1833. if (!self::checkTrendArrays($yValues, $xValues)) {
  1834. return PHPExcel_Calculation_Functions::VALUE();
  1835. }
  1836. $yValueCount = count($yValues);
  1837. $xValueCount = count($xValues);
  1838. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1839. return PHPExcel_Calculation_Functions::NA();
  1840. } elseif ($yValueCount == 1) {
  1841. return 0;
  1842. }
  1843. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
  1844. if ($stats) {
  1845. return array(
  1846. array(
  1847. $bestFitLinear->getSlope(),
  1848. $bestFitLinear->getSlopeSE(),
  1849. $bestFitLinear->getGoodnessOfFit(),
  1850. $bestFitLinear->getF(),
  1851. $bestFitLinear->getSSRegression(),
  1852. ),
  1853. array(
  1854. $bestFitLinear->getIntersect(),
  1855. $bestFitLinear->getIntersectSE(),
  1856. $bestFitLinear->getStdevOfResiduals(),
  1857. $bestFitLinear->getDFResiduals(),
  1858. $bestFitLinear->getSSResiduals()
  1859. )
  1860. );
  1861. } else {
  1862. return array(
  1863. $bestFitLinear->getSlope(),
  1864. $bestFitLinear->getIntersect()
  1865. );
  1866. }
  1867. }
  1868. /**
  1869. * LOGEST
  1870. *
  1871. * Calculates an exponential curve that best fits the X and Y data series,
  1872. * and then returns an array that describes the line.
  1873. *
  1874. * @param array of mixed Data Series Y
  1875. * @param array of mixed Data Series X
  1876. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  1877. * @param boolean A logical value specifying whether to return additional regression statistics.
  1878. * @return array
  1879. */
  1880. public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false)
  1881. {
  1882. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  1883. $stats = (is_null($stats)) ? false : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats);
  1884. if (is_null($xValues)) {
  1885. $xValues = range(1, count(PHPExcel_Calculation_Functions::flattenArray($yValues)));
  1886. }
  1887. if (!self::checkTrendArrays($yValues, $xValues)) {
  1888. return PHPExcel_Calculation_Functions::VALUE();
  1889. }
  1890. $yValueCount = count($yValues);
  1891. $xValueCount = count($xValues);
  1892. foreach ($yValues as $value) {
  1893. if ($value <= 0.0) {
  1894. return PHPExcel_Calculation_Functions::NaN();
  1895. }
  1896. }
  1897. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  1898. return PHPExcel_Calculation_Functions::NA();
  1899. } elseif ($yValueCount == 1) {
  1900. return 1;
  1901. }
  1902. $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL, $yValues, $xValues, $const);
  1903. if ($stats) {
  1904. return array(
  1905. array(
  1906. $bestFitExponential->getSlope(),
  1907. $bestFitExponential->getSlopeSE(),
  1908. $bestFitExponential->getGoodnessOfFit(),
  1909. $bestFitExponential->getF(),
  1910. $bestFitExponential->getSSRegression(),
  1911. ),
  1912. array(
  1913. $bestFitExponential->getIntersect(),
  1914. $bestFitExponential->getIntersectSE(),
  1915. $bestFitExponential->getStdevOfResiduals(),
  1916. $bestFitExponential->getDFResiduals(),
  1917. $bestFitExponential->getSSResiduals()
  1918. )
  1919. );
  1920. } else {
  1921. return array(
  1922. $bestFitExponential->getSlope(),
  1923. $bestFitExponential->getIntersect()
  1924. );
  1925. }
  1926. }
  1927. /**
  1928. * LOGINV
  1929. *
  1930. * Returns the inverse of the normal cumulative distribution
  1931. *
  1932. * @param float $probability
  1933. * @param float $mean
  1934. * @param float $stdDev
  1935. * @return float
  1936. *
  1937. * @todo Try implementing P J Acklam's refinement algorithm for greater
  1938. * accuracy if I can get my head round the mathematics
  1939. * (as described at) http://home.online.no/~pjacklam/notes/invnorm/
  1940. */
  1941. public static function LOGINV($probability, $mean, $stdDev)
  1942. {
  1943. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  1944. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  1945. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1946. if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  1947. if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) {
  1948. return PHPExcel_Calculation_Functions::NaN();
  1949. }
  1950. return exp($mean + $stdDev * self::NORMSINV($probability));
  1951. }
  1952. return PHPExcel_Calculation_Functions::VALUE();
  1953. }
  1954. /**
  1955. * LOGNORMDIST
  1956. *
  1957. * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed
  1958. * with parameters mean and standard_dev.
  1959. *
  1960. * @param float $value
  1961. * @param float $mean
  1962. * @param float $stdDev
  1963. * @return float
  1964. */
  1965. public static function LOGNORMDIST($value, $mean, $stdDev)
  1966. {
  1967. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  1968. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  1969. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  1970. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  1971. if (($value <= 0) || ($stdDev <= 0)) {
  1972. return PHPExcel_Calculation_Functions::NaN();
  1973. }
  1974. return self::NORMSDIST((log($value) - $mean) / $stdDev);
  1975. }
  1976. return PHPExcel_Calculation_Functions::VALUE();
  1977. }
  1978. /**
  1979. * MAX
  1980. *
  1981. * MAX returns the value of the element of the values passed that has the highest value,
  1982. * with negative numbers considered smaller than positive numbers.
  1983. *
  1984. * Excel Function:
  1985. * MAX(value1[,value2[, ...]])
  1986. *
  1987. * @access public
  1988. * @category Statistical Functions
  1989. * @param mixed $arg,... Data values
  1990. * @return float
  1991. */
  1992. public static function MAX()
  1993. {
  1994. $returnValue = null;
  1995. // Loop through arguments
  1996. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  1997. foreach ($aArgs as $arg) {
  1998. // Is it a numeric value?
  1999. if ((is_numeric($arg)) && (!is_string($arg))) {
  2000. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2001. $returnValue = $arg;
  2002. }
  2003. }
  2004. }
  2005. if (is_null($returnValue)) {
  2006. return 0;
  2007. }
  2008. return $returnValue;
  2009. }
  2010. /**
  2011. * MAXA
  2012. *
  2013. * Returns the greatest value in a list of arguments, including numbers, text, and logical values
  2014. *
  2015. * Excel Function:
  2016. * MAXA(value1[,value2[, ...]])
  2017. *
  2018. * @access public
  2019. * @category Statistical Functions
  2020. * @param mixed $arg,... Data values
  2021. * @return float
  2022. */
  2023. public static function MAXA()
  2024. {
  2025. $returnValue = null;
  2026. // Loop through arguments
  2027. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2028. foreach ($aArgs as $arg) {
  2029. // Is it a numeric value?
  2030. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  2031. if (is_bool($arg)) {
  2032. $arg = (integer) $arg;
  2033. } elseif (is_string($arg)) {
  2034. $arg = 0;
  2035. }
  2036. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2037. $returnValue = $arg;
  2038. }
  2039. }
  2040. }
  2041. if (is_null($returnValue)) {
  2042. return 0;
  2043. }
  2044. return $returnValue;
  2045. }
  2046. /**
  2047. * MAXIF
  2048. *
  2049. * Counts the maximum value within a range of cells that contain numbers within the list of arguments
  2050. *
  2051. * Excel Function:
  2052. * MAXIF(value1[,value2[, ...]],condition)
  2053. *
  2054. * @access public
  2055. * @category Mathematical and Trigonometric Functions
  2056. * @param mixed $arg,... Data values
  2057. * @param string $condition The criteria that defines which cells will be checked.
  2058. * @return float
  2059. */
  2060. public static function MAXIF($aArgs, $condition, $sumArgs = array())
  2061. {
  2062. $returnValue = null;
  2063. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  2064. $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
  2065. if (empty($sumArgs)) {
  2066. $sumArgs = $aArgs;
  2067. }
  2068. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  2069. // Loop through arguments
  2070. foreach ($aArgs as $key => $arg) {
  2071. if (!is_numeric($arg)) {
  2072. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  2073. }
  2074. $testCondition = '='.$arg.$condition;
  2075. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  2076. if ((is_null($returnValue)) || ($arg > $returnValue)) {
  2077. $returnValue = $arg;
  2078. }
  2079. }
  2080. }
  2081. return $returnValue;
  2082. }
  2083. /**
  2084. * MEDIAN
  2085. *
  2086. * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
  2087. *
  2088. * Excel Function:
  2089. * MEDIAN(value1[,value2[, ...]])
  2090. *
  2091. * @access public
  2092. * @category Statistical Functions
  2093. * @param mixed $arg,... Data values
  2094. * @return float
  2095. */
  2096. public static function MEDIAN()
  2097. {
  2098. $returnValue = PHPExcel_Calculation_Functions::NaN();
  2099. $mArgs = array();
  2100. // Loop through arguments
  2101. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2102. foreach ($aArgs as $arg) {
  2103. // Is it a numeric value?
  2104. if ((is_numeric($arg)) && (!is_string($arg))) {
  2105. $mArgs[] = $arg;
  2106. }
  2107. }
  2108. $mValueCount = count($mArgs);
  2109. if ($mValueCount > 0) {
  2110. sort($mArgs, SORT_NUMERIC);
  2111. $mValueCount = $mValueCount / 2;
  2112. if ($mValueCount == floor($mValueCount)) {
  2113. $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
  2114. } else {
  2115. $mValueCount = floor($mValueCount);
  2116. $returnValue = $mArgs[$mValueCount];
  2117. }
  2118. }
  2119. return $returnValue;
  2120. }
  2121. /**
  2122. * MIN
  2123. *
  2124. * MIN returns the value of the element of the values passed that has the smallest value,
  2125. * with negative numbers considered smaller than positive numbers.
  2126. *
  2127. * Excel Function:
  2128. * MIN(value1[,value2[, ...]])
  2129. *
  2130. * @access public
  2131. * @category Statistical Functions
  2132. * @param mixed $arg,... Data values
  2133. * @return float
  2134. */
  2135. public static function MIN()
  2136. {
  2137. $returnValue = null;
  2138. // Loop through arguments
  2139. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2140. foreach ($aArgs as $arg) {
  2141. // Is it a numeric value?
  2142. if ((is_numeric($arg)) && (!is_string($arg))) {
  2143. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2144. $returnValue = $arg;
  2145. }
  2146. }
  2147. }
  2148. if (is_null($returnValue)) {
  2149. return 0;
  2150. }
  2151. return $returnValue;
  2152. }
  2153. /**
  2154. * MINA
  2155. *
  2156. * Returns the smallest value in a list of arguments, including numbers, text, and logical values
  2157. *
  2158. * Excel Function:
  2159. * MINA(value1[,value2[, ...]])
  2160. *
  2161. * @access public
  2162. * @category Statistical Functions
  2163. * @param mixed $arg,... Data values
  2164. * @return float
  2165. */
  2166. public static function MINA()
  2167. {
  2168. $returnValue = null;
  2169. // Loop through arguments
  2170. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2171. foreach ($aArgs as $arg) {
  2172. // Is it a numeric value?
  2173. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
  2174. if (is_bool($arg)) {
  2175. $arg = (integer) $arg;
  2176. } elseif (is_string($arg)) {
  2177. $arg = 0;
  2178. }
  2179. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2180. $returnValue = $arg;
  2181. }
  2182. }
  2183. }
  2184. if (is_null($returnValue)) {
  2185. return 0;
  2186. }
  2187. return $returnValue;
  2188. }
  2189. /**
  2190. * MINIF
  2191. *
  2192. * Returns the minimum value within a range of cells that contain numbers within the list of arguments
  2193. *
  2194. * Excel Function:
  2195. * MINIF(value1[,value2[, ...]],condition)
  2196. *
  2197. * @access public
  2198. * @category Mathematical and Trigonometric Functions
  2199. * @param mixed $arg,... Data values
  2200. * @param string $condition The criteria that defines which cells will be checked.
  2201. * @return float
  2202. */
  2203. public static function MINIF($aArgs, $condition, $sumArgs = array())
  2204. {
  2205. $returnValue = null;
  2206. $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs);
  2207. $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs);
  2208. if (empty($sumArgs)) {
  2209. $sumArgs = $aArgs;
  2210. }
  2211. $condition = PHPExcel_Calculation_Functions::ifCondition($condition);
  2212. // Loop through arguments
  2213. foreach ($aArgs as $key => $arg) {
  2214. if (!is_numeric($arg)) {
  2215. $arg = PHPExcel_Calculation::wrapResult(strtoupper($arg));
  2216. }
  2217. $testCondition = '='.$arg.$condition;
  2218. if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) {
  2219. if ((is_null($returnValue)) || ($arg < $returnValue)) {
  2220. $returnValue = $arg;
  2221. }
  2222. }
  2223. }
  2224. return $returnValue;
  2225. }
  2226. //
  2227. // Special variant of array_count_values that isn't limited to strings and integers,
  2228. // but can work with floating point numbers as values
  2229. //
  2230. private static function modeCalc($data)
  2231. {
  2232. $frequencyArray = array();
  2233. foreach ($data as $datum) {
  2234. $found = false;
  2235. foreach ($frequencyArray as $key => $value) {
  2236. if ((string) $value['value'] == (string) $datum) {
  2237. ++$frequencyArray[$key]['frequency'];
  2238. $found = true;
  2239. break;
  2240. }
  2241. }
  2242. if (!$found) {
  2243. $frequencyArray[] = array(
  2244. 'value' => $datum,
  2245. 'frequency' => 1
  2246. );
  2247. }
  2248. }
  2249. foreach ($frequencyArray as $key => $value) {
  2250. $frequencyList[$key] = $value['frequency'];
  2251. $valueList[$key] = $value['value'];
  2252. }
  2253. array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
  2254. if ($frequencyArray[0]['frequency'] == 1) {
  2255. return PHPExcel_Calculation_Functions::NA();
  2256. }
  2257. return $frequencyArray[0]['value'];
  2258. }
  2259. /**
  2260. * MODE
  2261. *
  2262. * Returns the most frequently occurring, or repetitive, value in an array or range of data
  2263. *
  2264. * Excel Function:
  2265. * MODE(value1[,value2[, ...]])
  2266. *
  2267. * @access public
  2268. * @category Statistical Functions
  2269. * @param mixed $arg,... Data values
  2270. * @return float
  2271. */
  2272. public static function MODE()
  2273. {
  2274. $returnValue = PHPExcel_Calculation_Functions::NA();
  2275. // Loop through arguments
  2276. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2277. $mArgs = array();
  2278. foreach ($aArgs as $arg) {
  2279. // Is it a numeric value?
  2280. if ((is_numeric($arg)) && (!is_string($arg))) {
  2281. $mArgs[] = $arg;
  2282. }
  2283. }
  2284. if (!empty($mArgs)) {
  2285. return self::modeCalc($mArgs);
  2286. }
  2287. return $returnValue;
  2288. }
  2289. /**
  2290. * NEGBINOMDIST
  2291. *
  2292. * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that
  2293. * there will be number_f failures before the number_s-th success, when the constant
  2294. * probability of a success is probability_s. This function is similar to the binomial
  2295. * distribution, except that the number of successes is fixed, and the number of trials is
  2296. * variable. Like the binomial, trials are assumed to be independent.
  2297. *
  2298. * @param float $failures Number of Failures
  2299. * @param float $successes Threshold number of Successes
  2300. * @param float $probability Probability of success on each trial
  2301. * @return float
  2302. *
  2303. */
  2304. public static function NEGBINOMDIST($failures, $successes, $probability)
  2305. {
  2306. $failures = floor(PHPExcel_Calculation_Functions::flattenSingleValue($failures));
  2307. $successes = floor(PHPExcel_Calculation_Functions::flattenSingleValue($successes));
  2308. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  2309. if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) {
  2310. if (($failures < 0) || ($successes < 1)) {
  2311. return PHPExcel_Calculation_Functions::NaN();
  2312. } elseif (($probability < 0) || ($probability > 1)) {
  2313. return PHPExcel_Calculation_Functions::NaN();
  2314. }
  2315. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  2316. if (($failures + $successes - 1) <= 0) {
  2317. return PHPExcel_Calculation_Functions::NaN();
  2318. }
  2319. }
  2320. return (PHPExcel_Calculation_MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures));
  2321. }
  2322. return PHPExcel_Calculation_Functions::VALUE();
  2323. }
  2324. /**
  2325. * NORMDIST
  2326. *
  2327. * Returns the normal distribution for the specified mean and standard deviation. This
  2328. * function has a very wide range of applications in statistics, including hypothesis
  2329. * testing.
  2330. *
  2331. * @param float $value
  2332. * @param float $mean Mean Value
  2333. * @param float $stdDev Standard Deviation
  2334. * @param boolean $cumulative
  2335. * @return float
  2336. *
  2337. */
  2338. public static function NORMDIST($value, $mean, $stdDev, $cumulative)
  2339. {
  2340. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2341. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2342. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2343. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2344. if ($stdDev < 0) {
  2345. return PHPExcel_Calculation_Functions::NaN();
  2346. }
  2347. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  2348. if ($cumulative) {
  2349. return 0.5 * (1 + PHPExcel_Calculation_Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2))));
  2350. } else {
  2351. return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev))));
  2352. }
  2353. }
  2354. }
  2355. return PHPExcel_Calculation_Functions::VALUE();
  2356. }
  2357. /**
  2358. * NORMINV
  2359. *
  2360. * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation.
  2361. *
  2362. * @param float $value
  2363. * @param float $mean Mean Value
  2364. * @param float $stdDev Standard Deviation
  2365. * @return float
  2366. *
  2367. */
  2368. public static function NORMINV($probability, $mean, $stdDev)
  2369. {
  2370. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  2371. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2372. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2373. if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2374. if (($probability < 0) || ($probability > 1)) {
  2375. return PHPExcel_Calculation_Functions::NaN();
  2376. }
  2377. if ($stdDev < 0) {
  2378. return PHPExcel_Calculation_Functions::NaN();
  2379. }
  2380. return (self::inverseNcdf($probability) * $stdDev) + $mean;
  2381. }
  2382. return PHPExcel_Calculation_Functions::VALUE();
  2383. }
  2384. /**
  2385. * NORMSDIST
  2386. *
  2387. * Returns the standard normal cumulative distribution function. The distribution has
  2388. * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a
  2389. * table of standard normal curve areas.
  2390. *
  2391. * @param float $value
  2392. * @return float
  2393. */
  2394. public static function NORMSDIST($value)
  2395. {
  2396. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2397. return self::NORMDIST($value, 0, 1, true);
  2398. }
  2399. /**
  2400. * NORMSINV
  2401. *
  2402. * Returns the inverse of the standard normal cumulative distribution
  2403. *
  2404. * @param float $value
  2405. * @return float
  2406. */
  2407. public static function NORMSINV($value)
  2408. {
  2409. return self::NORMINV($value, 0, 1);
  2410. }
  2411. /**
  2412. * PERCENTILE
  2413. *
  2414. * Returns the nth percentile of values in a range..
  2415. *
  2416. * Excel Function:
  2417. * PERCENTILE(value1[,value2[, ...]],entry)
  2418. *
  2419. * @access public
  2420. * @category Statistical Functions
  2421. * @param mixed $arg,... Data values
  2422. * @param float $entry Percentile value in the range 0..1, inclusive.
  2423. * @return float
  2424. */
  2425. public static function PERCENTILE()
  2426. {
  2427. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2428. // Calculate
  2429. $entry = array_pop($aArgs);
  2430. if ((is_numeric($entry)) && (!is_string($entry))) {
  2431. if (($entry < 0) || ($entry > 1)) {
  2432. return PHPExcel_Calculation_Functions::NaN();
  2433. }
  2434. $mArgs = array();
  2435. foreach ($aArgs as $arg) {
  2436. // Is it a numeric value?
  2437. if ((is_numeric($arg)) && (!is_string($arg))) {
  2438. $mArgs[] = $arg;
  2439. }
  2440. }
  2441. $mValueCount = count($mArgs);
  2442. if ($mValueCount > 0) {
  2443. sort($mArgs);
  2444. $count = self::COUNT($mArgs);
  2445. $index = $entry * ($count-1);
  2446. $iBase = floor($index);
  2447. if ($index == $iBase) {
  2448. return $mArgs[$index];
  2449. } else {
  2450. $iNext = $iBase + 1;
  2451. $iProportion = $index - $iBase;
  2452. return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
  2453. }
  2454. }
  2455. }
  2456. return PHPExcel_Calculation_Functions::VALUE();
  2457. }
  2458. /**
  2459. * PERCENTRANK
  2460. *
  2461. * Returns the rank of a value in a data set as a percentage of the data set.
  2462. *
  2463. * @param array of number An array of, or a reference to, a list of numbers.
  2464. * @param number The number whose rank you want to find.
  2465. * @param number The number of significant digits for the returned percentage value.
  2466. * @return float
  2467. */
  2468. public static function PERCENTRANK($valueSet, $value, $significance = 3)
  2469. {
  2470. $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
  2471. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2472. $significance = (is_null($significance)) ? 3 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($significance);
  2473. foreach ($valueSet as $key => $valueEntry) {
  2474. if (!is_numeric($valueEntry)) {
  2475. unset($valueSet[$key]);
  2476. }
  2477. }
  2478. sort($valueSet, SORT_NUMERIC);
  2479. $valueCount = count($valueSet);
  2480. if ($valueCount == 0) {
  2481. return PHPExcel_Calculation_Functions::NaN();
  2482. }
  2483. $valueAdjustor = $valueCount - 1;
  2484. if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
  2485. return PHPExcel_Calculation_Functions::NA();
  2486. }
  2487. $pos = array_search($value, $valueSet);
  2488. if ($pos === false) {
  2489. $pos = 0;
  2490. $testValue = $valueSet[0];
  2491. while ($testValue < $value) {
  2492. $testValue = $valueSet[++$pos];
  2493. }
  2494. --$pos;
  2495. $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
  2496. }
  2497. return round($pos / $valueAdjustor, $significance);
  2498. }
  2499. /**
  2500. * PERMUT
  2501. *
  2502. * Returns the number of permutations for a given number of objects that can be
  2503. * selected from number objects. A permutation is any set or subset of objects or
  2504. * events where internal order is significant. Permutations are different from
  2505. * combinations, for which the internal order is not significant. Use this function
  2506. * for lottery-style probability calculations.
  2507. *
  2508. * @param int $numObjs Number of different objects
  2509. * @param int $numInSet Number of objects in each permutation
  2510. * @return int Number of permutations
  2511. */
  2512. public static function PERMUT($numObjs, $numInSet)
  2513. {
  2514. $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs);
  2515. $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet);
  2516. if ((is_numeric($numObjs)) && (is_numeric($numInSet))) {
  2517. $numInSet = floor($numInSet);
  2518. if ($numObjs < $numInSet) {
  2519. return PHPExcel_Calculation_Functions::NaN();
  2520. }
  2521. return round(PHPExcel_Calculation_MathTrig::FACT($numObjs) / PHPExcel_Calculation_MathTrig::FACT($numObjs - $numInSet));
  2522. }
  2523. return PHPExcel_Calculation_Functions::VALUE();
  2524. }
  2525. /**
  2526. * POISSON
  2527. *
  2528. * Returns the Poisson distribution. A common application of the Poisson distribution
  2529. * is predicting the number of events over a specific time, such as the number of
  2530. * cars arriving at a toll plaza in 1 minute.
  2531. *
  2532. * @param float $value
  2533. * @param float $mean Mean Value
  2534. * @param boolean $cumulative
  2535. * @return float
  2536. *
  2537. */
  2538. public static function POISSON($value, $mean, $cumulative)
  2539. {
  2540. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2541. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2542. if ((is_numeric($value)) && (is_numeric($mean))) {
  2543. if (($value < 0) || ($mean <= 0)) {
  2544. return PHPExcel_Calculation_Functions::NaN();
  2545. }
  2546. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  2547. if ($cumulative) {
  2548. $summer = 0;
  2549. for ($i = 0; $i <= floor($value); ++$i) {
  2550. $summer += pow($mean, $i) / PHPExcel_Calculation_MathTrig::FACT($i);
  2551. }
  2552. return exp(0-$mean) * $summer;
  2553. } else {
  2554. return (exp(0-$mean) * pow($mean, $value)) / PHPExcel_Calculation_MathTrig::FACT($value);
  2555. }
  2556. }
  2557. }
  2558. return PHPExcel_Calculation_Functions::VALUE();
  2559. }
  2560. /**
  2561. * QUARTILE
  2562. *
  2563. * Returns the quartile of a data set.
  2564. *
  2565. * Excel Function:
  2566. * QUARTILE(value1[,value2[, ...]],entry)
  2567. *
  2568. * @access public
  2569. * @category Statistical Functions
  2570. * @param mixed $arg,... Data values
  2571. * @param int $entry Quartile value in the range 1..3, inclusive.
  2572. * @return float
  2573. */
  2574. public static function QUARTILE()
  2575. {
  2576. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2577. // Calculate
  2578. $entry = floor(array_pop($aArgs));
  2579. if ((is_numeric($entry)) && (!is_string($entry))) {
  2580. $entry /= 4;
  2581. if (($entry < 0) || ($entry > 1)) {
  2582. return PHPExcel_Calculation_Functions::NaN();
  2583. }
  2584. return self::PERCENTILE($aArgs, $entry);
  2585. }
  2586. return PHPExcel_Calculation_Functions::VALUE();
  2587. }
  2588. /**
  2589. * RANK
  2590. *
  2591. * Returns the rank of a number in a list of numbers.
  2592. *
  2593. * @param number The number whose rank you want to find.
  2594. * @param array of number An array of, or a reference to, a list of numbers.
  2595. * @param mixed Order to sort the values in the value set
  2596. * @return float
  2597. */
  2598. public static function RANK($value, $valueSet, $order = 0)
  2599. {
  2600. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2601. $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet);
  2602. $order = (is_null($order)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($order);
  2603. foreach ($valueSet as $key => $valueEntry) {
  2604. if (!is_numeric($valueEntry)) {
  2605. unset($valueSet[$key]);
  2606. }
  2607. }
  2608. if ($order == 0) {
  2609. rsort($valueSet, SORT_NUMERIC);
  2610. } else {
  2611. sort($valueSet, SORT_NUMERIC);
  2612. }
  2613. $pos = array_search($value, $valueSet);
  2614. if ($pos === false) {
  2615. return PHPExcel_Calculation_Functions::NA();
  2616. }
  2617. return ++$pos;
  2618. }
  2619. /**
  2620. * RSQ
  2621. *
  2622. * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
  2623. *
  2624. * @param array of mixed Data Series Y
  2625. * @param array of mixed Data Series X
  2626. * @return float
  2627. */
  2628. public static function RSQ($yValues, $xValues)
  2629. {
  2630. if (!self::checkTrendArrays($yValues, $xValues)) {
  2631. return PHPExcel_Calculation_Functions::VALUE();
  2632. }
  2633. $yValueCount = count($yValues);
  2634. $xValueCount = count($xValues);
  2635. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2636. return PHPExcel_Calculation_Functions::NA();
  2637. } elseif ($yValueCount == 1) {
  2638. return PHPExcel_Calculation_Functions::DIV0();
  2639. }
  2640. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2641. return $bestFitLinear->getGoodnessOfFit();
  2642. }
  2643. /**
  2644. * SKEW
  2645. *
  2646. * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
  2647. * of a distribution around its mean. Positive skewness indicates a distribution with an
  2648. * asymmetric tail extending toward more positive values. Negative skewness indicates a
  2649. * distribution with an asymmetric tail extending toward more negative values.
  2650. *
  2651. * @param array Data Series
  2652. * @return float
  2653. */
  2654. public static function SKEW()
  2655. {
  2656. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2657. $mean = self::AVERAGE($aArgs);
  2658. $stdDev = self::STDEV($aArgs);
  2659. $count = $summer = 0;
  2660. // Loop through arguments
  2661. foreach ($aArgs as $k => $arg) {
  2662. if ((is_bool($arg)) &&
  2663. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2664. } else {
  2665. // Is it a numeric value?
  2666. if ((is_numeric($arg)) && (!is_string($arg))) {
  2667. $summer += pow((($arg - $mean) / $stdDev), 3);
  2668. ++$count;
  2669. }
  2670. }
  2671. }
  2672. if ($count > 2) {
  2673. return $summer * ($count / (($count-1) * ($count-2)));
  2674. }
  2675. return PHPExcel_Calculation_Functions::DIV0();
  2676. }
  2677. /**
  2678. * SLOPE
  2679. *
  2680. * Returns the slope of the linear regression line through data points in known_y's and known_x's.
  2681. *
  2682. * @param array of mixed Data Series Y
  2683. * @param array of mixed Data Series X
  2684. * @return float
  2685. */
  2686. public static function SLOPE($yValues, $xValues)
  2687. {
  2688. if (!self::checkTrendArrays($yValues, $xValues)) {
  2689. return PHPExcel_Calculation_Functions::VALUE();
  2690. }
  2691. $yValueCount = count($yValues);
  2692. $xValueCount = count($xValues);
  2693. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2694. return PHPExcel_Calculation_Functions::NA();
  2695. } elseif ($yValueCount == 1) {
  2696. return PHPExcel_Calculation_Functions::DIV0();
  2697. }
  2698. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2699. return $bestFitLinear->getSlope();
  2700. }
  2701. /**
  2702. * SMALL
  2703. *
  2704. * Returns the nth smallest value in a data set. You can use this function to
  2705. * select a value based on its relative standing.
  2706. *
  2707. * Excel Function:
  2708. * SMALL(value1[,value2[, ...]],entry)
  2709. *
  2710. * @access public
  2711. * @category Statistical Functions
  2712. * @param mixed $arg,... Data values
  2713. * @param int $entry Position (ordered from the smallest) in the array or range of data to return
  2714. * @return float
  2715. */
  2716. public static function SMALL()
  2717. {
  2718. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  2719. // Calculate
  2720. $entry = array_pop($aArgs);
  2721. if ((is_numeric($entry)) && (!is_string($entry))) {
  2722. $mArgs = array();
  2723. foreach ($aArgs as $arg) {
  2724. // Is it a numeric value?
  2725. if ((is_numeric($arg)) && (!is_string($arg))) {
  2726. $mArgs[] = $arg;
  2727. }
  2728. }
  2729. $count = self::COUNT($mArgs);
  2730. $entry = floor(--$entry);
  2731. if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
  2732. return PHPExcel_Calculation_Functions::NaN();
  2733. }
  2734. sort($mArgs);
  2735. return $mArgs[$entry];
  2736. }
  2737. return PHPExcel_Calculation_Functions::VALUE();
  2738. }
  2739. /**
  2740. * STANDARDIZE
  2741. *
  2742. * Returns a normalized value from a distribution characterized by mean and standard_dev.
  2743. *
  2744. * @param float $value Value to normalize
  2745. * @param float $mean Mean Value
  2746. * @param float $stdDev Standard Deviation
  2747. * @return float Standardized value
  2748. */
  2749. public static function STANDARDIZE($value, $mean, $stdDev)
  2750. {
  2751. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2752. $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean);
  2753. $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev);
  2754. if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
  2755. if ($stdDev <= 0) {
  2756. return PHPExcel_Calculation_Functions::NaN();
  2757. }
  2758. return ($value - $mean) / $stdDev ;
  2759. }
  2760. return PHPExcel_Calculation_Functions::VALUE();
  2761. }
  2762. /**
  2763. * STDEV
  2764. *
  2765. * Estimates standard deviation based on a sample. The standard deviation is a measure of how
  2766. * widely values are dispersed from the average value (the mean).
  2767. *
  2768. * Excel Function:
  2769. * STDEV(value1[,value2[, ...]])
  2770. *
  2771. * @access public
  2772. * @category Statistical Functions
  2773. * @param mixed $arg,... Data values
  2774. * @return float
  2775. */
  2776. public static function STDEV()
  2777. {
  2778. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2779. // Return value
  2780. $returnValue = null;
  2781. $aMean = self::AVERAGE($aArgs);
  2782. if (!is_null($aMean)) {
  2783. $aCount = -1;
  2784. foreach ($aArgs as $k => $arg) {
  2785. if ((is_bool($arg)) &&
  2786. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  2787. $arg = (integer) $arg;
  2788. }
  2789. // Is it a numeric value?
  2790. if ((is_numeric($arg)) && (!is_string($arg))) {
  2791. if (is_null($returnValue)) {
  2792. $returnValue = pow(($arg - $aMean), 2);
  2793. } else {
  2794. $returnValue += pow(($arg - $aMean), 2);
  2795. }
  2796. ++$aCount;
  2797. }
  2798. }
  2799. // Return
  2800. if (($aCount > 0) && ($returnValue >= 0)) {
  2801. return sqrt($returnValue / $aCount);
  2802. }
  2803. }
  2804. return PHPExcel_Calculation_Functions::DIV0();
  2805. }
  2806. /**
  2807. * STDEVA
  2808. *
  2809. * Estimates standard deviation based on a sample, including numbers, text, and logical values
  2810. *
  2811. * Excel Function:
  2812. * STDEVA(value1[,value2[, ...]])
  2813. *
  2814. * @access public
  2815. * @category Statistical Functions
  2816. * @param mixed $arg,... Data values
  2817. * @return float
  2818. */
  2819. public static function STDEVA()
  2820. {
  2821. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2822. $returnValue = null;
  2823. $aMean = self::AVERAGEA($aArgs);
  2824. if (!is_null($aMean)) {
  2825. $aCount = -1;
  2826. foreach ($aArgs as $k => $arg) {
  2827. if ((is_bool($arg)) &&
  2828. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2829. } else {
  2830. // Is it a numeric value?
  2831. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  2832. if (is_bool($arg)) {
  2833. $arg = (integer) $arg;
  2834. } elseif (is_string($arg)) {
  2835. $arg = 0;
  2836. }
  2837. if (is_null($returnValue)) {
  2838. $returnValue = pow(($arg - $aMean), 2);
  2839. } else {
  2840. $returnValue += pow(($arg - $aMean), 2);
  2841. }
  2842. ++$aCount;
  2843. }
  2844. }
  2845. }
  2846. if (($aCount > 0) && ($returnValue >= 0)) {
  2847. return sqrt($returnValue / $aCount);
  2848. }
  2849. }
  2850. return PHPExcel_Calculation_Functions::DIV0();
  2851. }
  2852. /**
  2853. * STDEVP
  2854. *
  2855. * Calculates standard deviation based on the entire population
  2856. *
  2857. * Excel Function:
  2858. * STDEVP(value1[,value2[, ...]])
  2859. *
  2860. * @access public
  2861. * @category Statistical Functions
  2862. * @param mixed $arg,... Data values
  2863. * @return float
  2864. */
  2865. public static function STDEVP()
  2866. {
  2867. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2868. $returnValue = null;
  2869. $aMean = self::AVERAGE($aArgs);
  2870. if (!is_null($aMean)) {
  2871. $aCount = 0;
  2872. foreach ($aArgs as $k => $arg) {
  2873. if ((is_bool($arg)) &&
  2874. ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) {
  2875. $arg = (integer) $arg;
  2876. }
  2877. // Is it a numeric value?
  2878. if ((is_numeric($arg)) && (!is_string($arg))) {
  2879. if (is_null($returnValue)) {
  2880. $returnValue = pow(($arg - $aMean), 2);
  2881. } else {
  2882. $returnValue += pow(($arg - $aMean), 2);
  2883. }
  2884. ++$aCount;
  2885. }
  2886. }
  2887. if (($aCount > 0) && ($returnValue >= 0)) {
  2888. return sqrt($returnValue / $aCount);
  2889. }
  2890. }
  2891. return PHPExcel_Calculation_Functions::DIV0();
  2892. }
  2893. /**
  2894. * STDEVPA
  2895. *
  2896. * Calculates standard deviation based on the entire population, including numbers, text, and logical values
  2897. *
  2898. * Excel Function:
  2899. * STDEVPA(value1[,value2[, ...]])
  2900. *
  2901. * @access public
  2902. * @category Statistical Functions
  2903. * @param mixed $arg,... Data values
  2904. * @return float
  2905. */
  2906. public static function STDEVPA()
  2907. {
  2908. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  2909. $returnValue = null;
  2910. $aMean = self::AVERAGEA($aArgs);
  2911. if (!is_null($aMean)) {
  2912. $aCount = 0;
  2913. foreach ($aArgs as $k => $arg) {
  2914. if ((is_bool($arg)) &&
  2915. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  2916. } else {
  2917. // Is it a numeric value?
  2918. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  2919. if (is_bool($arg)) {
  2920. $arg = (integer) $arg;
  2921. } elseif (is_string($arg)) {
  2922. $arg = 0;
  2923. }
  2924. if (is_null($returnValue)) {
  2925. $returnValue = pow(($arg - $aMean), 2);
  2926. } else {
  2927. $returnValue += pow(($arg - $aMean), 2);
  2928. }
  2929. ++$aCount;
  2930. }
  2931. }
  2932. }
  2933. if (($aCount > 0) && ($returnValue >= 0)) {
  2934. return sqrt($returnValue / $aCount);
  2935. }
  2936. }
  2937. return PHPExcel_Calculation_Functions::DIV0();
  2938. }
  2939. /**
  2940. * STEYX
  2941. *
  2942. * Returns the standard error of the predicted y-value for each x in the regression.
  2943. *
  2944. * @param array of mixed Data Series Y
  2945. * @param array of mixed Data Series X
  2946. * @return float
  2947. */
  2948. public static function STEYX($yValues, $xValues)
  2949. {
  2950. if (!self::checkTrendArrays($yValues, $xValues)) {
  2951. return PHPExcel_Calculation_Functions::VALUE();
  2952. }
  2953. $yValueCount = count($yValues);
  2954. $xValueCount = count($xValues);
  2955. if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
  2956. return PHPExcel_Calculation_Functions::NA();
  2957. } elseif ($yValueCount == 1) {
  2958. return PHPExcel_Calculation_Functions::DIV0();
  2959. }
  2960. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues);
  2961. return $bestFitLinear->getStdevOfResiduals();
  2962. }
  2963. /**
  2964. * TDIST
  2965. *
  2966. * Returns the probability of Student's T distribution.
  2967. *
  2968. * @param float $value Value for the function
  2969. * @param float $degrees degrees of freedom
  2970. * @param float $tails number of tails (1 or 2)
  2971. * @return float
  2972. */
  2973. public static function TDIST($value, $degrees, $tails)
  2974. {
  2975. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  2976. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  2977. $tails = floor(PHPExcel_Calculation_Functions::flattenSingleValue($tails));
  2978. if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) {
  2979. if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
  2980. return PHPExcel_Calculation_Functions::NaN();
  2981. }
  2982. // tdist, which finds the probability that corresponds to a given value
  2983. // of t with k degrees of freedom. This algorithm is translated from a
  2984. // pascal function on p81 of "Statistical Computing in Pascal" by D
  2985. // Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
  2986. // London). The above Pascal algorithm is itself a translation of the
  2987. // fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
  2988. // Laboratory as reported in (among other places) "Applied Statistics
  2989. // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
  2990. // Horwood Ltd.; W. Sussex, England).
  2991. $tterm = $degrees;
  2992. $ttheta = atan2($value, sqrt($tterm));
  2993. $tc = cos($ttheta);
  2994. $ts = sin($ttheta);
  2995. $tsum = 0;
  2996. if (($degrees % 2) == 1) {
  2997. $ti = 3;
  2998. $tterm = $tc;
  2999. } else {
  3000. $ti = 2;
  3001. $tterm = 1;
  3002. }
  3003. $tsum = $tterm;
  3004. while ($ti < $degrees) {
  3005. $tterm *= $tc * $tc * ($ti - 1) / $ti;
  3006. $tsum += $tterm;
  3007. $ti += 2;
  3008. }
  3009. $tsum *= $ts;
  3010. if (($degrees % 2) == 1) {
  3011. $tsum = M_2DIVPI * ($tsum + $ttheta);
  3012. }
  3013. $tValue = 0.5 * (1 + $tsum);
  3014. if ($tails == 1) {
  3015. return 1 - abs($tValue);
  3016. } else {
  3017. return 1 - abs((1 - $tValue) - $tValue);
  3018. }
  3019. }
  3020. return PHPExcel_Calculation_Functions::VALUE();
  3021. }
  3022. /**
  3023. * TINV
  3024. *
  3025. * Returns the one-tailed probability of the chi-squared distribution.
  3026. *
  3027. * @param float $probability Probability for the function
  3028. * @param float $degrees degrees of freedom
  3029. * @return float
  3030. */
  3031. public static function TINV($probability, $degrees)
  3032. {
  3033. $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability);
  3034. $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees));
  3035. if ((is_numeric($probability)) && (is_numeric($degrees))) {
  3036. $xLo = 100;
  3037. $xHi = 0;
  3038. $x = $xNew = 1;
  3039. $dx = 1;
  3040. $i = 0;
  3041. while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) {
  3042. // Apply Newton-Raphson step
  3043. $result = self::TDIST($x, $degrees, 2);
  3044. $error = $result - $probability;
  3045. if ($error == 0.0) {
  3046. $dx = 0;
  3047. } elseif ($error < 0.0) {
  3048. $xLo = $x;
  3049. } else {
  3050. $xHi = $x;
  3051. }
  3052. // Avoid division by zero
  3053. if ($result != 0.0) {
  3054. $dx = $error / $result;
  3055. $xNew = $x - $dx;
  3056. }
  3057. // If the NR fails to converge (which for example may be the
  3058. // case if the initial guess is too rough) we apply a bisection
  3059. // step to determine a more narrow interval around the root.
  3060. if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
  3061. $xNew = ($xLo + $xHi) / 2;
  3062. $dx = $xNew - $x;
  3063. }
  3064. $x = $xNew;
  3065. }
  3066. if ($i == MAX_ITERATIONS) {
  3067. return PHPExcel_Calculation_Functions::NA();
  3068. }
  3069. return round($x, 12);
  3070. }
  3071. return PHPExcel_Calculation_Functions::VALUE();
  3072. }
  3073. /**
  3074. * TREND
  3075. *
  3076. * Returns values along a linear trend
  3077. *
  3078. * @param array of mixed Data Series Y
  3079. * @param array of mixed Data Series X
  3080. * @param array of mixed Values of X for which we want to find Y
  3081. * @param boolean A logical value specifying whether to force the intersect to equal 0.
  3082. * @return array of float
  3083. */
  3084. public static function TREND($yValues, $xValues = array(), $newValues = array(), $const = true)
  3085. {
  3086. $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues);
  3087. $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues);
  3088. $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues);
  3089. $const = (is_null($const)) ? true : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const);
  3090. $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR, $yValues, $xValues, $const);
  3091. if (empty($newValues)) {
  3092. $newValues = $bestFitLinear->getXValues();
  3093. }
  3094. $returnArray = array();
  3095. foreach ($newValues as $xValue) {
  3096. $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
  3097. }
  3098. return $returnArray;
  3099. }
  3100. /**
  3101. * TRIMMEAN
  3102. *
  3103. * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
  3104. * taken by excluding a percentage of data points from the top and bottom tails
  3105. * of a data set.
  3106. *
  3107. * Excel Function:
  3108. * TRIMEAN(value1[,value2[, ...]], $discard)
  3109. *
  3110. * @access public
  3111. * @category Statistical Functions
  3112. * @param mixed $arg,... Data values
  3113. * @param float $discard Percentage to discard
  3114. * @return float
  3115. */
  3116. public static function TRIMMEAN()
  3117. {
  3118. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3119. // Calculate
  3120. $percent = array_pop($aArgs);
  3121. if ((is_numeric($percent)) && (!is_string($percent))) {
  3122. if (($percent < 0) || ($percent > 1)) {
  3123. return PHPExcel_Calculation_Functions::NaN();
  3124. }
  3125. $mArgs = array();
  3126. foreach ($aArgs as $arg) {
  3127. // Is it a numeric value?
  3128. if ((is_numeric($arg)) && (!is_string($arg))) {
  3129. $mArgs[] = $arg;
  3130. }
  3131. }
  3132. $discard = floor(self::COUNT($mArgs) * $percent / 2);
  3133. sort($mArgs);
  3134. for ($i=0; $i < $discard; ++$i) {
  3135. array_pop($mArgs);
  3136. array_shift($mArgs);
  3137. }
  3138. return self::AVERAGE($mArgs);
  3139. }
  3140. return PHPExcel_Calculation_Functions::VALUE();
  3141. }
  3142. /**
  3143. * VARFunc
  3144. *
  3145. * Estimates variance based on a sample.
  3146. *
  3147. * Excel Function:
  3148. * VAR(value1[,value2[, ...]])
  3149. *
  3150. * @access public
  3151. * @category Statistical Functions
  3152. * @param mixed $arg,... Data values
  3153. * @return float
  3154. */
  3155. public static function VARFunc()
  3156. {
  3157. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3158. $summerA = $summerB = 0;
  3159. // Loop through arguments
  3160. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3161. $aCount = 0;
  3162. foreach ($aArgs as $arg) {
  3163. if (is_bool($arg)) {
  3164. $arg = (integer) $arg;
  3165. }
  3166. // Is it a numeric value?
  3167. if ((is_numeric($arg)) && (!is_string($arg))) {
  3168. $summerA += ($arg * $arg);
  3169. $summerB += $arg;
  3170. ++$aCount;
  3171. }
  3172. }
  3173. if ($aCount > 1) {
  3174. $summerA *= $aCount;
  3175. $summerB *= $summerB;
  3176. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  3177. }
  3178. return $returnValue;
  3179. }
  3180. /**
  3181. * VARA
  3182. *
  3183. * Estimates variance based on a sample, including numbers, text, and logical values
  3184. *
  3185. * Excel Function:
  3186. * VARA(value1[,value2[, ...]])
  3187. *
  3188. * @access public
  3189. * @category Statistical Functions
  3190. * @param mixed $arg,... Data values
  3191. * @return float
  3192. */
  3193. public static function VARA()
  3194. {
  3195. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3196. $summerA = $summerB = 0;
  3197. // Loop through arguments
  3198. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  3199. $aCount = 0;
  3200. foreach ($aArgs as $k => $arg) {
  3201. if ((is_string($arg)) &&
  3202. (PHPExcel_Calculation_Functions::isValue($k))) {
  3203. return PHPExcel_Calculation_Functions::VALUE();
  3204. } elseif ((is_string($arg)) &&
  3205. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  3206. } else {
  3207. // Is it a numeric value?
  3208. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  3209. if (is_bool($arg)) {
  3210. $arg = (integer) $arg;
  3211. } elseif (is_string($arg)) {
  3212. $arg = 0;
  3213. }
  3214. $summerA += ($arg * $arg);
  3215. $summerB += $arg;
  3216. ++$aCount;
  3217. }
  3218. }
  3219. }
  3220. if ($aCount > 1) {
  3221. $summerA *= $aCount;
  3222. $summerB *= $summerB;
  3223. $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
  3224. }
  3225. return $returnValue;
  3226. }
  3227. /**
  3228. * VARP
  3229. *
  3230. * Calculates variance based on the entire population
  3231. *
  3232. * Excel Function:
  3233. * VARP(value1[,value2[, ...]])
  3234. *
  3235. * @access public
  3236. * @category Statistical Functions
  3237. * @param mixed $arg,... Data values
  3238. * @return float
  3239. */
  3240. public static function VARP()
  3241. {
  3242. // Return value
  3243. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3244. $summerA = $summerB = 0;
  3245. // Loop through arguments
  3246. $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args());
  3247. $aCount = 0;
  3248. foreach ($aArgs as $arg) {
  3249. if (is_bool($arg)) {
  3250. $arg = (integer) $arg;
  3251. }
  3252. // Is it a numeric value?
  3253. if ((is_numeric($arg)) && (!is_string($arg))) {
  3254. $summerA += ($arg * $arg);
  3255. $summerB += $arg;
  3256. ++$aCount;
  3257. }
  3258. }
  3259. if ($aCount > 0) {
  3260. $summerA *= $aCount;
  3261. $summerB *= $summerB;
  3262. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  3263. }
  3264. return $returnValue;
  3265. }
  3266. /**
  3267. * VARPA
  3268. *
  3269. * Calculates variance based on the entire population, including numbers, text, and logical values
  3270. *
  3271. * Excel Function:
  3272. * VARPA(value1[,value2[, ...]])
  3273. *
  3274. * @access public
  3275. * @category Statistical Functions
  3276. * @param mixed $arg,... Data values
  3277. * @return float
  3278. */
  3279. public static function VARPA()
  3280. {
  3281. $returnValue = PHPExcel_Calculation_Functions::DIV0();
  3282. $summerA = $summerB = 0;
  3283. // Loop through arguments
  3284. $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args());
  3285. $aCount = 0;
  3286. foreach ($aArgs as $k => $arg) {
  3287. if ((is_string($arg)) &&
  3288. (PHPExcel_Calculation_Functions::isValue($k))) {
  3289. return PHPExcel_Calculation_Functions::VALUE();
  3290. } elseif ((is_string($arg)) &&
  3291. (!PHPExcel_Calculation_Functions::isMatrixValue($k))) {
  3292. } else {
  3293. // Is it a numeric value?
  3294. if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
  3295. if (is_bool($arg)) {
  3296. $arg = (integer) $arg;
  3297. } elseif (is_string($arg)) {
  3298. $arg = 0;
  3299. }
  3300. $summerA += ($arg * $arg);
  3301. $summerB += $arg;
  3302. ++$aCount;
  3303. }
  3304. }
  3305. }
  3306. if ($aCount > 0) {
  3307. $summerA *= $aCount;
  3308. $summerB *= $summerB;
  3309. $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
  3310. }
  3311. return $returnValue;
  3312. }
  3313. /**
  3314. * WEIBULL
  3315. *
  3316. * Returns the Weibull distribution. Use this distribution in reliability
  3317. * analysis, such as calculating a device's mean time to failure.
  3318. *
  3319. * @param float $value
  3320. * @param float $alpha Alpha Parameter
  3321. * @param float $beta Beta Parameter
  3322. * @param boolean $cumulative
  3323. * @return float
  3324. *
  3325. */
  3326. public static function WEIBULL($value, $alpha, $beta, $cumulative)
  3327. {
  3328. $value = PHPExcel_Calculation_Functions::flattenSingleValue($value);
  3329. $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha);
  3330. $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta);
  3331. if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) {
  3332. if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) {
  3333. return PHPExcel_Calculation_Functions::NaN();
  3334. }
  3335. if ((is_numeric($cumulative)) || (is_bool($cumulative))) {
  3336. if ($cumulative) {
  3337. return 1 - exp(0 - pow($value / $beta, $alpha));
  3338. } else {
  3339. return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha));
  3340. }
  3341. }
  3342. }
  3343. return PHPExcel_Calculation_Functions::VALUE();
  3344. }
  3345. /**
  3346. * ZTEST
  3347. *
  3348. * Returns the Weibull distribution. Use this distribution in reliability
  3349. * analysis, such as calculating a device's mean time to failure.
  3350. *
  3351. * @param float $dataSet
  3352. * @param float $m0 Alpha Parameter
  3353. * @param float $sigma Beta Parameter
  3354. * @param boolean $cumulative
  3355. * @return float
  3356. *
  3357. */
  3358. public static function ZTEST($dataSet, $m0, $sigma = null)
  3359. {
  3360. $dataSet = PHPExcel_Calculation_Functions::flattenArrayIndexed($dataSet);
  3361. $m0 = PHPExcel_Calculation_Functions::flattenSingleValue($m0);
  3362. $sigma = PHPExcel_Calculation_Functions::flattenSingleValue($sigma);
  3363. if (is_null($sigma)) {
  3364. $sigma = self::STDEV($dataSet);
  3365. }
  3366. $n = count($dataSet);
  3367. return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0) / ($sigma / SQRT($n)));
  3368. }
  3369. }