/intra-export/plugins/sfPhpExcelPlugin/lib/PHPExcel/PHPExcel/Calculation/Functions.php
PHP | 9537 lines | 5838 code | 883 blank | 2816 comment | 1625 complexity | 64fdd85c24b60c417984f8dfc72f777b MD5 | raw file
Possible License(s): ISC, AGPL-3.0, LGPL-2.1, BSD-3-Clause, LGPL-3.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * PHPExcel
- *
- * Copyright (c) 2006 - 2009 PHPExcel
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * @category PHPExcel
- * @package PHPExcel_Calculation
- * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
- * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
- * @version ##VERSION##, ##DATE##
- */
- define('EPS', 2.22e-16);
- define('MAX_VALUE', 1.2e308);
- define('LOG_GAMMA_X_MAX_VALUE', 2.55e305);
- define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099);
- define('XMININ', 2.23e-308);
- define('MAX_ITERATIONS', 150);
- define('PRECISION', 8.88E-016);
- define('EULER', 2.71828182845904523536);
- $savedPrecision = ini_get('precision');
- if ($savedPrecision < 16) {
- ini_set('precision',16);
- }
- /** PHPExcel_Cell */
- require_once 'PHPExcel/Cell.php';
- /** PHPExcel_Cell_DataType */
- require_once 'PHPExcel/Cell/DataType.php';
- /** PHPExcel_Shared_Date */
- require_once 'PHPExcel/Shared/Date.php';
- /** PHPExcel_Shared_Date */
- require_once 'PHPExcel/Shared/JAMA/Matrix.php';
- include_once('PHPExcel/Shared/trend/trendClass.php');
- /**
- * PHPExcel_Calculation_Functions
- *
- * @category PHPExcel
- * @package PHPExcel_Calculation
- * @copyright Copyright (c) 2006 - 2009 PHPExcel (http://www.codeplex.com/PHPExcel)
- */
- class PHPExcel_Calculation_Functions {
- /** constants */
- const COMPATIBILITY_EXCEL = 'Excel';
- const COMPATIBILITY_GNUMERIC = 'Gnumeric';
- const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc';
- const RETURNDATE_PHP_NUMERIC = 'P';
- const RETURNDATE_PHP_OBJECT = 'O';
- const RETURNDATE_EXCEL = 'E';
- /**
- * Compatibility mode to use for error checking and responses
- *
- * @var string
- */
- private static $compatibilityMode = self::COMPATIBILITY_EXCEL;
- /**
- * Data Type to use when returning date values
- *
- * @var integer
- */
- private static $ReturnDateType = self::RETURNDATE_PHP_NUMERIC;
- /**
- * List of error codes
- *
- * @var array
- */
- private static $_errorCodes = array( 'null' => '#NULL!',
- 'divisionbyzero' => '#DIV/0!',
- 'value' => '#VALUE!',
- 'reference' => '#REF!',
- 'name' => '#NAME?',
- 'num' => '#NUM!',
- 'na' => '#N/A',
- 'gettingdata' => '#GETTING_DATA'
- );
- /**
- * Set the Compatibility Mode
- *
- * @param string $compatibilityMode Compatibility Mode
- * Permitted values are:
- * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
- * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
- * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
- * @return boolean (Success or Failure)
- */
- public static function setCompatibilityMode($compatibilityMode) {
- if (($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
- ($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
- ($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
- self::$compatibilityMode = $compatibilityMode;
- return True;
- }
- return False;
- } // function setCompatibilityMode()
- /**
- * Return the current Compatibility Mode
- *
- * @return string $compatibilityMode Compatibility Mode
- * Possible Return values are:
- * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
- * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
- * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
- */
- public static function getCompatibilityMode() {
- return self::$compatibilityMode;
- } // function getCompatibilityMode()
- /**
- * Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized or PHP Object)
- *
- * @param integer $returnDateType Return Date Format
- * Permitted values are:
- * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
- * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
- * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
- * @return boolean Success or failure
- */
- public static function setReturnDateType($returnDateType) {
- if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) ||
- ($returnDateType == self::RETURNDATE_PHP_OBJECT) ||
- ($returnDateType == self::RETURNDATE_EXCEL)) {
- self::$ReturnDateType = $returnDateType;
- return True;
- }
- return False;
- } // function setReturnDateType()
- /**
- * Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized or PHP Object)
- *
- * @return integer $returnDateType Return Date Format
- * Possible Return values are:
- * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
- * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
- * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
- */
- public static function getReturnDateType() {
- return self::$ReturnDateType;
- } // function getReturnDateType()
- /**
- * DUMMY
- *
- * @return string #NAME?
- */
- public static function DUMMY() {
- return '#Not Yet Implemented';
- } // function DUMMY()
- /**
- * NA
- *
- * @return string #N/A!
- */
- public static function NA() {
- return self::$_errorCodes['na'];
- } // function NA()
- /**
- * LOGICAL_AND
- *
- * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE.
- *
- * Booleans arguments are treated as True or False as appropriate
- * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
- * If any argument value is a string, or a Null, it is ignored
- *
- * Quirk of Excel:
- * String values passed directly to the function rather than through a cell reference
- * e.g.=AND(1,"A",1)
- * will return a #VALUE! error, _not_ ignoring the string.
- * This behaviour is not replicated
- *
- * @param array of mixed Data Series
- * @return boolean
- */
- public static function LOGICAL_AND() {
- // Return value
- $returnValue = True;
- // Loop through the arguments
- $aArgs = self::flattenArray(func_get_args());
- $argCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a boolean value?
- if (is_bool($arg)) {
- $returnValue = $returnValue && $arg;
- ++$argCount;
- } elseif ((is_numeric($arg)) && (!is_string($arg))) {
- $returnValue = $returnValue && ($arg != 0);
- ++$argCount;
- }
- }
- // Return
- if ($argCount == 0) {
- return self::$_errorCodes['value'];
- }
- return $returnValue;
- } // function LOGICAL_AND()
- /**
- * LOGICAL_OR
- *
- * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE.
- *
- * Booleans arguments are treated as True or False as appropriate
- * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False
- * If any argument value is a string, or a Null, it is ignored
- *
- * @param array of mixed Data Series
- * @return boolean
- */
- public static function LOGICAL_OR() {
- // Return value
- $returnValue = False;
- // Loop through the arguments
- $aArgs = self::flattenArray(func_get_args());
- $argCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a boolean value?
- if (is_bool($arg)) {
- $returnValue = $returnValue || $arg;
- ++$argCount;
- } elseif ((is_numeric($arg)) && (!is_string($arg))) {
- $returnValue = $returnValue || ($arg != 0);
- ++$argCount;
- }
- }
- // Return
- if ($argCount == 0) {
- return self::$_errorCodes['value'];
- }
- return $returnValue;
- } // function LOGICAL_OR()
- /**
- * LOGICAL_FALSE
- *
- * Returns FALSE.
- *
- * @return boolean
- */
- public static function LOGICAL_FALSE() {
- return False;
- } // function LOGICAL_FALSE()
- /**
- * LOGICAL_TRUE
- *
- * Returns TRUE.
- *
- * @return boolean
- */
- public static function LOGICAL_TRUE() {
- return True;
- } // function LOGICAL_TRUE()
- /**
- * ATAN2
- *
- * This function calculates the arc tangent of the two variables x and y. It is similar to
- * calculating the arc tangent of y / x, except that the signs of both arguments are used
- * to determine the quadrant of the result.
- * Note that Excel reverses the arguments, so we need to reverse them here before calling the
- * standard PHP atan() function
- *
- * @param float $x Number
- * @param float $y Number
- * @return float Square Root of Number * Pi
- */
- public static function REVERSE_ATAN2($x, $y) {
- $x = self::flattenSingleValue($x);
- $y = self::flattenSingleValue($y);
- return atan2($y, $x);
- } // function REVERSE_ATAN2()
- /**
- * SUM
- *
- * SUM computes the sum of all the values and cells referenced in the argument list.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function SUM() {
- // Return value
- $returnValue = 0;
- // Loop through the arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $returnValue += $arg;
- }
- }
- // Return
- return $returnValue;
- } // function SUM()
- /**
- * SUMSQ
- *
- * Returns the sum of the squares of the arguments
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function SUMSQ() {
- // Return value
- $returnValue = 0;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $returnValue += pow($arg,2);
- }
- }
- // Return
- return $returnValue;
- } // function SUMSQ()
- /**
- * PRODUCT
- *
- * PRODUCT returns the product of all the values and cells referenced in the argument list.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function PRODUCT() {
- // Return value
- $returnValue = null;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = $arg;
- } else {
- $returnValue *= $arg;
- }
- }
- }
- // Return
- if (is_null($returnValue)) {
- return 0;
- }
- return $returnValue;
- } // function PRODUCT()
- /**
- * QUOTIENT
- *
- * QUOTIENT function returns the integer portion of a division.numerator is the divided number
- * and denominator is the divisor.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function QUOTIENT() {
- // Return value
- $returnValue = null;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- if (($returnValue == 0) || ($arg == 0)) {
- $returnValue = 0;
- } else {
- $returnValue = $arg;
- }
- } else {
- if (($returnValue == 0) || ($arg == 0)) {
- $returnValue = 0;
- } else {
- $returnValue /= $arg;
- }
- }
- }
- }
- // Return
- return intval($returnValue);
- } // function QUOTIENT()
- /**
- * MIN
- *
- * MIN returns the value of the element of the values passed that has the smallest value,
- * with negative numbers considered smaller than positive numbers.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MIN() {
- // Return value
- $returnValue = null;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if ((is_null($returnValue)) || ($arg < $returnValue)) {
- $returnValue = $arg;
- }
- }
- }
- // Return
- if(is_null($returnValue)) {
- return 0;
- }
- return $returnValue;
- } // function MIN()
- /**
- * MINA
- *
- * Returns the smallest value in a list of arguments, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MINA() {
- // Return value
- $returnValue = null;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- if ((is_null($returnValue)) || ($arg < $returnValue)) {
- $returnValue = $arg;
- }
- }
- }
- // Return
- if(is_null($returnValue)) {
- return 0;
- }
- return $returnValue;
- } // function MINA()
- /**
- * SMALL
- *
- * Returns the nth smallest value in a data set. You can use this function to
- * select a value based on its relative standing.
- *
- * @param array of mixed Data Series
- * @param float Entry in the series to return
- * @return float
- */
- public static function SMALL() {
- $aArgs = self::flattenArray(func_get_args());
- // Calculate
- $n = array_pop($aArgs);
- if ((is_numeric($n)) && (!is_string($n))) {
- $mArgs = array();
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- $count = self::COUNT($mArgs);
- $n = floor(--$n);
- if (($n < 0) || ($n >= $count) || ($count == 0)) {
- return self::$_errorCodes['num'];
- }
- sort($mArgs);
- return $mArgs[$n];
- }
- return self::$_errorCodes['value'];
- }
- /**
- * MAX
- *
- * MAX returns the value of the element of the values passed that has the highest value,
- * with negative numbers considered smaller than positive numbers.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MAX() {
- // Return value
- $returnValue = null;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if ((is_null($returnValue)) || ($arg > $returnValue)) {
- $returnValue = $arg;
- }
- }
- }
- // Return
- if(is_null($returnValue)) {
- return 0;
- }
- return $returnValue;
- }
- /**
- * MAXA
- *
- * Returns the greatest value in a list of arguments, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MAXA() {
- // Return value
- $returnValue = null;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- if ((is_null($returnValue)) || ($arg > $returnValue)) {
- $returnValue = $arg;
- }
- }
- }
- // Return
- if(is_null($returnValue)) {
- return 0;
- }
- return $returnValue;
- }
- /**
- * LARGE
- *
- * Returns the nth largest value in a data set. You can use this function to
- * select a value based on its relative standing.
- *
- * @param array of mixed Data Series
- * @param float Entry in the series to return
- * @return float
- *
- */
- public static function LARGE() {
- $aArgs = self::flattenArray(func_get_args());
- // Calculate
- $n = floor(array_pop($aArgs));
- if ((is_numeric($n)) && (!is_string($n))) {
- $mArgs = array();
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- $count = self::COUNT($mArgs);
- $n = floor(--$n);
- if (($n < 0) || ($n >= $count) || ($count == 0)) {
- return self::$_errorCodes['num'];
- }
- rsort($mArgs);
- return $mArgs[$n];
- }
- return self::$_errorCodes['value'];
- }
- /**
- * PERCENTILE
- *
- * Returns the nth percentile of values in a range..
- *
- * @param array of mixed Data Series
- * @param float $entry Entry in the series to return
- * @return float
- */
- public static function PERCENTILE() {
- $aArgs = self::flattenArray(func_get_args());
- // Calculate
- $entry = array_pop($aArgs);
- if ((is_numeric($entry)) && (!is_string($entry))) {
- if (($entry < 0) || ($entry > 1)) {
- return self::$_errorCodes['num'];
- }
- $mArgs = array();
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- $mValueCount = count($mArgs);
- if ($mValueCount > 0) {
- sort($mArgs);
- $count = self::COUNT($mArgs);
- $index = $entry * ($count-1);
- $iBase = floor($index);
- if ($index == $iBase) {
- return $mArgs[$index];
- } else {
- $iNext = $iBase + 1;
- $iProportion = $index - $iBase;
- return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ;
- }
- }
- }
- return self::$_errorCodes['value'];
- }
- /**
- * QUARTILE
- *
- * Returns the quartile of a data set.
- *
- * @param array of mixed Data Series
- * @param float $entry Entry in the series to return
- * @return float
- */
- public static function QUARTILE() {
- $aArgs = self::flattenArray(func_get_args());
- // Calculate
- $entry = floor(array_pop($aArgs));
- if ((is_numeric($entry)) && (!is_string($entry))) {
- $entry /= 4;
- if (($entry < 0) || ($entry > 1)) {
- return self::$_errorCodes['num'];
- }
- return self::PERCENTILE($aArgs,$entry);
- }
- return self::$_errorCodes['value'];
- }
- /**
- * COUNT
- *
- * Counts the number of cells that contain numbers within the list of arguments
- *
- * @param array of mixed Data Series
- * @return int
- */
- public static function COUNT() {
- // Return value
- $returnValue = 0;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
- $arg = (int) $arg;
- }
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- ++$returnValue;
- }
- }
- // Return
- return $returnValue;
- }
- /**
- * COUNTBLANK
- *
- * Counts the number of empty cells within the list of arguments
- *
- * @param array of mixed Data Series
- * @return int
- */
- public static function COUNTBLANK() {
- // Return value
- $returnValue = 0;
- // Loop trough arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a blank cell?
- if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) {
- ++$returnValue;
- }
- }
- // Return
- return $returnValue;
- }
- /**
- * COUNTA
- *
- * Counts the number of cells that are not empty within the list of arguments
- *
- * @param array of mixed Data Series
- * @return int
- */
- public static function COUNTA() {
- // Return value
- $returnValue = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric, boolean or string value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
- ++$returnValue;
- }
- }
- // Return
- return $returnValue;
- }
- /**
- * AVERAGE
- *
- * Returns the average (arithmetic mean) of the arguments
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function AVERAGE() {
- // Return value
- $returnValue = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
- $arg = (integer) $arg;
- }
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = $arg;
- } else {
- $returnValue += $arg;
- }
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 0) {
- return $returnValue / $aCount;
- } else {
- return self::$_errorCodes['divisionbyzero'];
- }
- }
- /**
- * AVERAGEA
- *
- * Returns the average of its arguments, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function AVERAGEA() {
- // Return value
- $returnValue = null;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- if (is_null($returnValue)) {
- $returnValue = $arg;
- } else {
- $returnValue += $arg;
- }
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 0) {
- return $returnValue / $aCount;
- } else {
- return self::$_errorCodes['divisionbyzero'];
- }
- }
- /**
- * MEDIAN
- *
- * Returns the median of the given numbers. The median is the number in the middle of a set of numbers.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MEDIAN() {
- // Return value
- $returnValue = self::$_errorCodes['num'];
- $mArgs = array();
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- $mValueCount = count($mArgs);
- if ($mValueCount > 0) {
- sort($mArgs,SORT_NUMERIC);
- $mValueCount = $mValueCount / 2;
- if ($mValueCount == floor($mValueCount)) {
- $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2;
- } else {
- $mValueCount == floor($mValueCount);
- $returnValue = $mArgs[$mValueCount];
- }
- }
- // Return
- return $returnValue;
- }
- //
- // Special variant of array_count_values that isn't limited to strings and integers,
- // but can work with floating point numbers as values
- //
- private static function modeCalc($data) {
- $frequencyArray = array();
- foreach($data as $datum) {
- $found = False;
- foreach($frequencyArray as $key => $value) {
- if ((string)$value['value'] == (string)$datum) {
- ++$frequencyArray[$key]['frequency'];
- $found = True;
- break;
- }
- }
- if (!$found) {
- $frequencyArray[] = array('value' => $datum,
- 'frequency' => 1 );
- }
- }
- foreach($frequencyArray as $key => $value) {
- $frequencyList[$key] = $value['frequency'];
- $valueList[$key] = $value['value'];
- }
- array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray);
- if ($frequencyArray[0]['frequency'] == 1) {
- return self::NA();
- }
- return $frequencyArray[0]['value'];
- }
- /**
- * MODE
- *
- * Returns the most frequently occurring, or repetitive, value in an array or range of data
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function MODE() {
- // Return value
- $returnValue = self::NA();
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $mArgs = array();
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- if (count($mArgs) > 0) {
- return self::modeCalc($mArgs);
- }
- // Return
- return $returnValue;
- }
- /**
- * DEVSQ
- *
- * Returns the sum of squares of deviations of data points from their sample mean.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function DEVSQ() {
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGE(func_get_args());
- if (!is_null($aMean)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = -1;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
- $arg = (int) $arg;
- }
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = pow(($arg - $aMean),2);
- } else {
- $returnValue += pow(($arg - $aMean),2);
- }
- ++$aCount;
- }
- }
- // Return
- if (is_null($returnValue)) {
- return self::$_errorCodes['num'];
- } else {
- return $returnValue;
- }
- }
- return self::NA();
- }
- /**
- * AVEDEV
- *
- * Returns the average of the absolute deviations of data points from their mean.
- * AVEDEV is a measure of the variability in a data set.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function AVEDEV() {
- $aArgs = self::flattenArray(func_get_args());
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGE($aArgs);
- if ($aMean != self::$_errorCodes['divisionbyzero']) {
- $aCount = 0;
- foreach ($aArgs as $arg) {
- if ((is_bool($arg)) && (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
- $arg = (integer) $arg;
- }
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = abs($arg - $aMean);
- } else {
- $returnValue += abs($arg - $aMean);
- }
- ++$aCount;
- }
- }
- // Return
- return $returnValue / $aCount ;
- }
- return self::$_errorCodes['num'];
- }
- /**
- * GEOMEAN
- *
- * Returns the geometric mean of an array or range of positive data. For example, you
- * can use GEOMEAN to calculate average growth rate given compound interest with
- * variable rates.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function GEOMEAN() {
- $aMean = self::PRODUCT(func_get_args());
- if (is_numeric($aMean) && ($aMean > 0)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = self::COUNT($aArgs) ;
- if (self::MIN($aArgs) > 0) {
- return pow($aMean, (1 / $aCount));
- }
- }
- return self::$_errorCodes['num'];
- }
- /**
- * HARMEAN
- *
- * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
- * arithmetic mean of reciprocals.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function HARMEAN() {
- // Return value
- $returnValue = self::NA();
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- if (self::MIN($aArgs) < 0) {
- return self::$_errorCodes['num'];
- }
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if ($arg <= 0) {
- return self::$_errorCodes['num'];
- }
- if (is_null($returnValue)) {
- $returnValue = (1 / $arg);
- } else {
- $returnValue += (1 / $arg);
- }
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 0) {
- return 1 / ($returnValue / $aCount);
- } else {
- return $returnValue;
- }
- }
- /**
- * TRIMMEAN
- *
- * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
- * taken by excluding a percentage of data points from the top and bottom tails
- * of a data set.
- *
- * @param array of mixed Data Series
- * @param float Percentage to discard
- * @return float
- */
- public static function TRIMMEAN() {
- $aArgs = self::flattenArray(func_get_args());
- // Calculate
- $percent = array_pop($aArgs);
- if ((is_numeric($percent)) && (!is_string($percent))) {
- if (($percent < 0) || ($percent > 1)) {
- return self::$_errorCodes['num'];
- }
- $mArgs = array();
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $mArgs[] = $arg;
- }
- }
- $discard = floor(self::COUNT($mArgs) * $percent / 2);
- sort($mArgs);
- for ($i=0; $i < $discard; ++$i) {
- array_pop($mArgs);
- array_shift($mArgs);
- }
- return self::AVERAGE($mArgs);
- }
- return self::$_errorCodes['value'];
- }
- /**
- * STDEV
- *
- * Estimates standard deviation based on a sample. The standard deviation is a measure of how
- * widely values are dispersed from the average value (the mean).
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function STDEV() {
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGE(func_get_args());
- if (!is_null($aMean)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = -1;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = pow(($arg - $aMean),2);
- } else {
- $returnValue += pow(($arg - $aMean),2);
- }
- ++$aCount;
- }
- }
- // Return
- if (($aCount > 0) && ($returnValue > 0)) {
- return sqrt($returnValue / $aCount);
- }
- }
- return self::$_errorCodes['divisionbyzero'];
- }
- /**
- * STDEVA
- *
- * Estimates standard deviation based on a sample, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function STDEVA() {
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGEA(func_get_args());
- if (!is_null($aMean)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = -1;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- if (is_null($returnValue)) {
- $returnValue = pow(($arg - $aMean),2);
- } else {
- $returnValue += pow(($arg - $aMean),2);
- }
- ++$aCount;
- }
- }
- // Return
- if (($aCount > 0) && ($returnValue > 0)) {
- return sqrt($returnValue / $aCount);
- }
- }
- return self::$_errorCodes['divisionbyzero'];
- }
- /**
- * STDEVP
- *
- * Calculates standard deviation based on the entire population
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function STDEVP() {
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGE(func_get_args());
- if (!is_null($aMean)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- if (is_null($returnValue)) {
- $returnValue = pow(($arg - $aMean),2);
- } else {
- $returnValue += pow(($arg - $aMean),2);
- }
- ++$aCount;
- }
- }
- // Return
- if (($aCount > 0) && ($returnValue > 0)) {
- return sqrt($returnValue / $aCount);
- }
- }
- return self::$_errorCodes['divisionbyzero'];
- }
- /**
- * STDEVPA
- *
- * Calculates standard deviation based on the entire population, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function STDEVPA() {
- // Return value
- $returnValue = null;
- $aMean = self::AVERAGEA(func_get_args());
- if (!is_null($aMean)) {
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- if (is_null($returnValue)) {
- $returnValue = pow(($arg - $aMean),2);
- } else {
- $returnValue += pow(($arg - $aMean),2);
- }
- ++$aCount;
- }
- }
- // Return
- if (($aCount > 0) && ($returnValue > 0)) {
- return sqrt($returnValue / $aCount);
- }
- }
- return self::$_errorCodes['divisionbyzero'];
- }
- /**
- * VARFunc
- *
- * Estimates variance based on a sample.
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function VARFunc() {
- // Return value
- $returnValue = self::$_errorCodes['divisionbyzero'];
- $summerA = $summerB = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $summerA += ($arg * $arg);
- $summerB += $arg;
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 1) {
- $summerA = $summerA * $aCount;
- $summerB = ($summerB * $summerB);
- $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
- }
- return $returnValue;
- }
- /**
- * VARA
- *
- * Estimates variance based on a sample, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function VARA() {
- // Return value
- $returnValue = self::$_errorCodes['divisionbyzero'];
- $summerA = $summerB = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- $summerA += ($arg * $arg);
- $summerB += $arg;
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 1) {
- $summerA = $summerA * $aCount;
- $summerB = ($summerB * $summerB);
- $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1));
- }
- return $returnValue;
- }
- /**
- * VARP
- *
- * Calculates variance based on the entire population
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function VARP() {
- // Return value
- $returnValue = self::$_errorCodes['divisionbyzero'];
- $summerA = $summerB = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) && (!is_string($arg))) {
- $summerA += ($arg * $arg);
- $summerB += $arg;
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 0) {
- $summerA = $summerA * $aCount;
- $summerB = ($summerB * $summerB);
- $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
- }
- return $returnValue;
- }
- /**
- * VARPA
- *
- * Calculates variance based on the entire population, including numbers, text, and logical values
- *
- * @param array of mixed Data Series
- * @return float
- */
- public static function VARPA() {
- // Return value
- $returnValue = self::$_errorCodes['divisionbyzero'];
- $summerA = $summerB = 0;
- // Loop through arguments
- $aArgs = self::flattenArray(func_get_args());
- $aCount = 0;
- foreach ($aArgs as $arg) {
- // Is it a numeric value?
- if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) {
- if (is_bool($arg)) {
- $arg = (integer) $arg;
- } elseif (is_string($arg)) {
- $arg = 0;
- }
- $summerA += ($arg * $arg);
- $summerB += $arg;
- ++$aCount;
- }
- }
- // Return
- if ($aCount > 0) {
- $summerA = $summerA * $aCount;
- $summerB = ($summerB * $summerB);
- $returnValue = ($summerA - $summerB) / ($aCount * $aCount);
- }
- return $returnValue;
- }
- /**
- * RANK
- *
- * Returns the rank of a number in a list of numbers.
- *
- * @param number The number whose rank you want to find.
- * @param array of number An array of, or a reference to, a list of numbers.
- * @param mixed Order to sort the values in the value set
- * @return float
- */
- public static function RANK($value,$valueSet,$order=0) {
- $value = self::flattenSingleValue($value);
- $valueSet = self::flattenArray($valueSet);
- $order = self::flattenSingleValue($order);
- foreach($valueSet as $key => $valueEntry) {
- if (!is_numeric($valueEntry)) {
- unset($valueSet[$key]);
- }
- }
- if ($order == 0) {
- rsort($valueSet,SORT_NUMERIC);
- } else {
- sort($valueSet,SORT_NUMERIC);
- }
- $pos = array_search($value,$valueSet);
- if ($pos === False) {
- return self::$_errorCodes['na'];
- }
- return ++$pos;
- } // function RANK()
- /**
- * PERCENTRANK
- *
- * Returns the rank of a value in a data set as a percentage of the data set.
- *
- * @param array of number An array of, or a reference to, a list of numbers.
- * @param number The number whose rank you want to find.
- * @param number The number of significant digits for the returned percentage value.
- * @return float
- */
- public static function PERCENTRANK($valueSet,$value,$significance=3) {
- $valueSet = self::flattenArray($valueSet);
- $value = self::flattenSingleValue($value);
- $significance = self::flattenSingleValue($significance);
- foreach($valueSet as $key => $valueEntry) {
- if (!is_numeric($valueEntry)) {
- unset($valueSet[$key]);
- }
- }
- sort($valueSet,SORT_NUMERIC);
- $valueCount = count($valueSet);
- if ($valueCount == 0) {
- return self::$_errorCodes['num'];
- }
- $valueAdjustor = $valueCount - 1;
- if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) {
- return self::$_errorCodes['na'];
- }
- $pos = array_search($value,$valueSet);
- if ($pos === False) {
- $pos = 0;
- $testValue = $valueSet[0];
- while ($testValue < $value) {
- $testValue = $valueSet[++$pos];
- }
- --$pos;
- $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos]));
- }
- return round($pos / $valueAdjustor,$significance);
- } // function PERCENTRANK()
- private static function _checkTrendArray($values) {
- foreach($values as $key => $value) {
- if ((is_bool($value)) || ($value == '')) {
- unset($values[$key]);
- } elseif (is_string($value)) {
- if (is_numeric($value)) {
- $values[$key] = (float) $value;
- } else {
- unset($values[$key]);
- }
- }
- }
- return $values;
- } // function _checkTrendArray()
- /**
- * INTERCEPT
- *
- * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function INTERCEPT($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getIntersect();
- } // function INTERCEPT()
- /**
- * RSQ
- *
- * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function RSQ($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getGoodnessOfFit();
- } // function RSQ()
- /**
- * SLOPE
- *
- * Returns the slope of the linear regression line through data points in known_y's and known_x's.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function SLOPE($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getSlope();
- } // function SLOPE()
- /**
- * STEYX
- *
- * Returns the standard error of the predicted y-value for each x in the regression.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function STEYX($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getStdevOfResiduals();
- } // function STEYX()
- /**
- * COVAR
- *
- * Returns covariance, the average of the products of deviations for each data point pair.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function COVAR($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getCovariance();
- } // function COVAR()
- /**
- * CORREL
- *
- * Returns covariance, the average of the products of deviations for each data point pair.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function CORREL($yValues,$xValues) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getCorrelation();
- } // function CORREL()
- /**
- * LINEST
- *
- * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data,
- * and then returns an array that describes the line.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @param boolean A logical value specifying whether to force the intersect to equal 0.
- * @param boolean A logical value specifying whether to return additional regression statistics.
- * @return array
- */
- public static function LINEST($yValues,$xValues,$const=True,$stats=False) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $const = (boolean) self::flattenSingleValue($const);
- $stats = (boolean) self::flattenSingleValue($stats);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const);
- if ($stats) {
- return array( array( $bestFitLinear->getSlope(),
- $bestFitLinear->getSlopeSE(),
- $bestFitLinear->getGoodnessOfFit(),
- $bestFitLinear->getF(),
- $bestFitLinear->getSSRegression(),
- ),
- array( $bestFitLinear->getIntersect(),
- $bestFitLinear->getIntersectSE(),
- $bestFitLinear->getStdevOfResiduals(),
- $bestFitLinear->getDFResiduals(),
- $bestFitLinear->getSSResiduals()
- )
- );
- } else {
- return array( $bestFitLinear->getSlope(),
- $bestFitLinear->getIntersect()
- );
- }
- } // function LINEST()
- /**
- * LOGEST
- *
- * Calculates an exponential curve that best fits the X and Y data series,
- * and then returns an array that describes the line.
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @param boolean A logical value specifying whether to force the intersect to equal 0.
- * @param boolean A logical value specifying whether to return additional regression statistics.
- * @return array
- */
- public static function LOGEST($yValues,$xValues,$const=True,$stats=False) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $const = (boolean) self::flattenSingleValue($const);
- $stats = (boolean) self::flattenSingleValue($stats);
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const);
- if ($stats) {
- return array( array( $bestFitExponential->getSlope(),
- $bestFitExponential->getSlopeSE(),
- $bestFitExponential->getGoodnessOfFit(),
- $bestFitExponential->getF(),
- $bestFitExponential->getSSRegression(),
- ),
- array( $bestFitExponential->getIntersect(),
- $bestFitExponential->getIntersectSE(),
- $bestFitExponential->getStdevOfResiduals(),
- $bestFitExponential->getDFResiduals(),
- $bestFitExponential->getSSResiduals()
- )
- );
- } else {
- return array( $bestFitExponential->getSlope(),
- $bestFitExponential->getIntersect()
- );
- }
- } // function LOGEST()
- /**
- * FORECAST
- *
- * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value.
- *
- * @param float Value of X for which we want to find Y
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @return float
- */
- public static function FORECAST($xValue,$yValues,$xValues) {
- $xValue = self::flattenSingleValue($xValue);
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- if (!is_numeric($xValue)) {
- return self::$_errorCodes['value'];
- }
- $yValues = self::_checkTrendArray($yValues);
- $yValueCount = count($yValues);
- $xValues = self::_checkTrendArray($xValues);
- $xValueCount = count($xValues);
- if (($yValueCount == 0) || ($yValueCount != $xValueCount)) {
- return self::$_errorCodes['na'];
- } elseif ($yValueCount == 1) {
- return self::$_errorCodes['divisionbyzero'];
- }
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues);
- return $bestFitLinear->getValueOfYForX($xValue);
- } // function FORECAST()
- /**
- * TREND
- *
- * Returns values along a linear trend
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @param array of mixed Values of X for which we want to find Y
- * @param boolean A logical value specifying whether to force the intersect to equal 0.
- * @return array of float
- */
- public static function TREND($yValues,$xValues=array(),$newValues=array(),$const=True) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $newValues = self::flattenArray($newValues);
- $const = (boolean) self::flattenSingleValue($const);
- $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const);
- if (count($newValues) == 0) {
- $newValues = $bestFitLinear->getXValues();
- }
- $returnArray = array();
- foreach($newValues as $xValue) {
- $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue);
- }
- return $returnArray;
- } // function TREND()
- /**
- * GROWTH
- *
- * Returns values along a predicted emponential trend
- *
- * @param array of mixed Data Series Y
- * @param array of mixed Data Series X
- * @param array of mixed Values of X for which we want to find Y
- * @param boolean A logical value specifying whether to force the intersect to equal 0.
- * @return array of float
- */
- public static function GROWTH($yValues,$xValues=array(),$newValues=array(),$const=True) {
- $yValues = self::flattenArray($yValues);
- $xValues = self::flattenArray($xValues);
- $newValues = self::flattenArray($newValues);
- $const = (boolean) self::flattenSingleValue($const);
- $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const);
- if (count($newValues) == 0) {
- $newValues = $bestFitExponential->getXValues();
- }
- $returnArray = array();
- foreach($newValues as $xValue) {
- $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue);
- }
- return $returnArray;
- } // function GROWTH()
- private static function _romanCut($num, $n) {
- return ($num - ($num % $n ) ) / $n;
- }
- public static function ROMAN ($aValue, $style=0)…
Large files files are truncated, but you can click here to view the full file