PageRenderTime 81ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

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

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