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