diff --git a/Classes/PHPExcel/Calculation.php b/Classes/PHPExcel/Calculation.php index cfe72f13..86a2f1e7 100644 --- a/Classes/PHPExcel/Calculation.php +++ b/Classes/PHPExcel/Calculation.php @@ -109,11 +109,16 @@ class PHPExcel_Calculation { /** * List of operators that can be used within formulae + * The true/false value indicates whether it is a binary operator or a unary operator * * @access private * @var array */ - private static $_operators = array('+', '-', '*', '/', '^', '&', '%', '~', '>', '<', '=', '>=', '<=', '<>', '|', ':'); + private static $_operators = array('+' => true, '-' => true, '*' => true, '/' => true, + '^' => true, '&' => true, '%' => false, '~' => false, + '>' => true, '<' => true, '=' => true, '>=' => true, + '<=' => true, '<>' => true, '|' => true, ':' => true + ); /** @@ -122,7 +127,11 @@ class PHPExcel_Calculation { * @access private * @var array */ - private static $_binaryOperators = array('+', '-', '*', '/', '^', '&', '>', '<', '=', '>=', '<=', '<>', '|', ':'); + private static $_binaryOperators = array('+' => true, '-' => true, '*' => true, '/' => true, + '^' => true, '&' => true, '>' => true, '<' => true, + '=' => true, '>=' => true, '<=' => true, '<>' => true, + '|' => true, ':' => true + ); /** * Flag to determine how formula errors should be handled @@ -201,11 +210,11 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ACCRINT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::ACCRINT', + 'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINT', 'argumentCount' => '4-7' ), 'ACCRINTM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::ACCRINTM', + 'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINTM', 'argumentCount' => '3-5' ), 'ACOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -217,19 +226,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ADDRESS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::CELL_ADDRESS', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::CELL_ADDRESS', 'argumentCount' => '2-5' ), 'AMORDEGRC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::AMORDEGRC', + 'functionCall' => 'PHPExcel_Calculation_Financial::AMORDEGRC', 'argumentCount' => '6,7' ), 'AMORLINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::AMORLINC', + 'functionCall' => 'PHPExcel_Calculation_Financial::AMORLINC', 'argumentCount' => '6,7' ), 'AND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_AND', + 'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_AND', 'argumentCount' => '1+' ), 'AREAS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, @@ -253,7 +262,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ATAN2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::REVERSE_ATAN2', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ATAN2', 'argumentCount' => '2' ), 'ATANH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -261,19 +270,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'AVEDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::AVEDEV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVEDEV', 'argumentCount' => '1+' ), 'AVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::AVERAGE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGE', 'argumentCount' => '1+' ), 'AVERAGEA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::AVERAGEA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEA', 'argumentCount' => '1+' ), 'AVERAGEIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEIF', 'argumentCount' => '2,3' ), 'AVERAGEIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -285,47 +294,47 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'BESSELI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BESSELI', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELI', 'argumentCount' => '2' ), 'BESSELJ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BESSELJ', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELJ', 'argumentCount' => '2' ), 'BESSELK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BESSELK', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELK', 'argumentCount' => '2' ), 'BESSELY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BESSELY', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELY', 'argumentCount' => '2' ), 'BETADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::BETADIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::BETADIST', 'argumentCount' => '3-5' ), 'BETAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::BETAINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::BETAINV', 'argumentCount' => '3-5' ), 'BIN2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BINTODEC', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTODEC', 'argumentCount' => '1' ), 'BIN2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BINTOHEX', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOHEX', 'argumentCount' => '1,2' ), 'BIN2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::BINTOOCT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOOCT', 'argumentCount' => '1,2' ), 'BINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::BINOMDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::BINOMDIST', 'argumentCount' => '4' ), 'CEILING' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::CEILING', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::CEILING', 'argumentCount' => '2' ), 'CELL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -333,15 +342,15 @@ class PHPExcel_Calculation { 'argumentCount' => '1,2' ), 'CHAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::CHARACTER', + 'functionCall' => 'PHPExcel_Calculation_TextData::CHARACTER', 'argumentCount' => '1' ), 'CHIDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CHIDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CHIDIST', 'argumentCount' => '2' ), 'CHIINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CHIINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CHIINV', 'argumentCount' => '2' ), 'CHITEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -349,48 +358,48 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'CHOOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::CHOOSE', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::CHOOSE', 'argumentCount' => '2+' ), 'CLEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::TRIMNONPRINTABLE', + 'functionCall' => 'PHPExcel_Calculation_TextData::TRIMNONPRINTABLE', 'argumentCount' => '1' ), 'CODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::ASCIICODE', + 'functionCall' => 'PHPExcel_Calculation_TextData::ASCIICODE', 'argumentCount' => '1' ), 'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMN', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMN', 'argumentCount' => '-1', 'passByReference' => array(true) ), 'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::COLUMNS', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMNS', 'argumentCount' => '1' ), 'COMBIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::COMBIN', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::COMBIN', 'argumentCount' => '2' ), 'COMPLEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::COMPLEX', + 'functionCall' => 'PHPExcel_Calculation_Engineering::COMPLEX', 'argumentCount' => '2,3' ), 'CONCATENATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::CONCATENATE', + 'functionCall' => 'PHPExcel_Calculation_TextData::CONCATENATE', 'argumentCount' => '1+' ), 'CONFIDENCE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CONFIDENCE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CONFIDENCE', 'argumentCount' => '3' ), 'CONVERT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::CONVERTUOM', + 'functionCall' => 'PHPExcel_Calculation_Engineering::CONVERTUOM', 'argumentCount' => '3' ), 'CORREL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CORREL', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL', 'argumentCount' => '2' ), 'COS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -402,19 +411,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'COUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUNT', + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNT', 'argumentCount' => '1+' ), 'COUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUNTA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTA', 'argumentCount' => '1+' ), 'COUNTBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUNTBLANK', + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTBLANK', 'argumentCount' => '1' ), 'COUNTIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUNTIF', + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTIF', 'argumentCount' => '2' ), 'COUNTIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -422,35 +431,35 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'COUPDAYBS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYBS', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYBS', 'argumentCount' => '3,4' ), 'COUPDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYS', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYS', 'argumentCount' => '3,4' ), 'COUPDAYSNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPDAYSNC', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYSNC', 'argumentCount' => '3,4' ), 'COUPNCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPNCD', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPNCD', 'argumentCount' => '3,4' ), 'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPNUM', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPNUM', 'argumentCount' => '3,4' ), 'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COUPPCD', + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPPCD', 'argumentCount' => '3,4' ), 'COVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::COVAR', + 'functionCall' => 'PHPExcel_Calculation_Statistical::COVAR', 'argumentCount' => '2' ), 'CRITBINOM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CRITBINOM', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CRITBINOM', 'argumentCount' => '3' ), 'CUBEKPIMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, @@ -482,23 +491,23 @@ class PHPExcel_Calculation { 'argumentCount' => '?' ), 'CUMIPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CUMIPMT', + 'functionCall' => 'PHPExcel_Calculation_Financial::CUMIPMT', 'argumentCount' => '6' ), 'CUMPRINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CUMPRINC', + 'functionCall' => 'PHPExcel_Calculation_Financial::CUMPRINC', 'argumentCount' => '6' ), 'DATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DATE', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATE', 'argumentCount' => '3' ), 'DATEDIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DATEDIF', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATEDIF', 'argumentCount' => '2,3' ), 'DATEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DATEVALUE', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATEVALUE', 'argumentCount' => '1' ), 'DAVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, @@ -506,15 +515,15 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'DAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DAYOFMONTH', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFMONTH', 'argumentCount' => '1' ), 'DAYS360' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DAYS360', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYS360', 'argumentCount' => '2,3' ), 'DB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DB', + 'functionCall' => 'PHPExcel_Calculation_Financial::DB', 'argumentCount' => '4,5' ), 'DCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, @@ -526,19 +535,19 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'DDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DDB', + 'functionCall' => 'PHPExcel_Calculation_Financial::DDB', 'argumentCount' => '4,5' ), 'DEC2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::DECTOBIN', + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOBIN', 'argumentCount' => '1,2' ), 'DEC2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::DECTOHEX', + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOHEX', 'argumentCount' => '1,2' ), 'DEC2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::DECTOOCT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOOCT', 'argumentCount' => '1,2' ), 'DEGREES' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -546,11 +555,11 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'DELTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::DELTA', + 'functionCall' => 'PHPExcel_Calculation_Engineering::DELTA', 'argumentCount' => '1,2' ), 'DEVSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DEVSQ', + 'functionCall' => 'PHPExcel_Calculation_Statistical::DEVSQ', 'argumentCount' => '1+' ), 'DGET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, @@ -558,7 +567,7 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'DISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DISC', + 'functionCall' => 'PHPExcel_Calculation_Financial::DISC', 'argumentCount' => '4,5' ), 'DMAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, @@ -570,15 +579,15 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'DOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::DOLLAR', + 'functionCall' => 'PHPExcel_Calculation_TextData::DOLLAR', 'argumentCount' => '1,2' ), 'DOLLARDE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DOLLARDE', + 'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARDE', 'argumentCount' => '2' ), 'DOLLARFR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DOLLARFR', + 'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARFR', 'argumentCount' => '2' ), 'DPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, @@ -610,23 +619,23 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'EDATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::EDATE', + 'functionCall' => 'PHPExcel_Calculation_DateTime::EDATE', 'argumentCount' => '2' ), 'EFFECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::EFFECT', + 'functionCall' => 'PHPExcel_Calculation_Financial::EFFECT', 'argumentCount' => '2' ), 'EOMONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::EOMONTH', + 'functionCall' => 'PHPExcel_Calculation_DateTime::EOMONTH', 'argumentCount' => '2' ), 'ERF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::ERF', + 'functionCall' => 'PHPExcel_Calculation_Engineering::ERF', 'argumentCount' => '1,2' ), 'ERFC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::ERFC', + 'functionCall' => 'PHPExcel_Calculation_Engineering::ERFC', 'argumentCount' => '1' ), 'ERROR.TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -634,7 +643,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'EVEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::EVEN', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::EVEN', 'argumentCount' => '1' ), 'EXACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, @@ -646,19 +655,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'EXPONDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::EXPONDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::EXPONDIST', 'argumentCount' => '3' ), 'FACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::FACT', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FACT', 'argumentCount' => '1' ), 'FACTDOUBLE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::FACTDOUBLE', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FACTDOUBLE', 'argumentCount' => '1' ), 'FALSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_FALSE', + 'functionCall' => 'PHPExcel_Calculation_Logical::FALSE', 'argumentCount' => '0' ), 'FDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -666,11 +675,11 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'FIND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHSENSITIVE', + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE', 'argumentCount' => '2,3' ), 'FINDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHSENSITIVE', + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE', 'argumentCount' => '2,3' ), 'FINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -678,23 +687,23 @@ class PHPExcel_Calculation { 'argumentCount' => '3' ), 'FISHER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::FISHER', + 'functionCall' => 'PHPExcel_Calculation_Statistical::FISHER', 'argumentCount' => '1' ), 'FISHERINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::FISHERINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::FISHERINV', 'argumentCount' => '1' ), 'FIXED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::FIXEDFORMAT', + 'functionCall' => 'PHPExcel_Calculation_TextData::FIXEDFORMAT', 'argumentCount' => '1-3' ), 'FLOOR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::FLOOR', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FLOOR', 'argumentCount' => '2' ), 'FORECAST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::FORECAST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::FORECAST', 'argumentCount' => '3' ), 'FREQUENCY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -706,35 +715,35 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'FV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::FV', + 'functionCall' => 'PHPExcel_Calculation_Financial::FV', 'argumentCount' => '3-5' ), 'FVSCHEDULE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::FVSCHEDULE', + 'functionCall' => 'PHPExcel_Calculation_Financial::FVSCHEDULE', 'argumentCount' => '2' ), 'GAMMADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::GAMMADIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMADIST', 'argumentCount' => '4' ), 'GAMMAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::GAMMAINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMAINV', 'argumentCount' => '3' ), 'GAMMALN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::GAMMALN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMALN', 'argumentCount' => '1' ), 'GCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::GCD', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::GCD', 'argumentCount' => '1+' ), 'GEOMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::GEOMEAN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::GEOMEAN', 'argumentCount' => '1+' ), 'GESTEP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::GESTEP', + 'functionCall' => 'PHPExcel_Calculation_Engineering::GESTEP', 'argumentCount' => '1,2' ), 'GETPIVOTDATA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, @@ -742,23 +751,23 @@ class PHPExcel_Calculation { 'argumentCount' => '2+' ), 'GROWTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::GROWTH', + 'functionCall' => 'PHPExcel_Calculation_Statistical::GROWTH', 'argumentCount' => '1-4' ), 'HARMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::HARMEAN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::HARMEAN', 'argumentCount' => '1+' ), 'HEX2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::HEXTOBIN', + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOBIN', 'argumentCount' => '1,2' ), 'HEX2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::HEXTODEC', + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTODEC', 'argumentCount' => '1' ), 'HEX2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::HEXTOOCT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOOCT', 'argumentCount' => '1,2' ), 'HLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, @@ -766,100 +775,100 @@ class PHPExcel_Calculation { 'argumentCount' => '3,4' ), 'HOUR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::HOUROFDAY', + 'functionCall' => 'PHPExcel_Calculation_DateTime::HOUROFDAY', 'argumentCount' => '1' ), 'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::HYPERLINK', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::HYPERLINK', 'argumentCount' => '1,2', 'passCellReference'=> true ), 'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::HYPGEOMDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::HYPGEOMDIST', 'argumentCount' => '4' ), 'IF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IF', + 'functionCall' => 'PHPExcel_Calculation_Logical::STATEMENT_IF', 'argumentCount' => '1-3' ), 'IFERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STATEMENT_IFERROR', + 'functionCall' => 'PHPExcel_Calculation_Logical::IFERROR', 'argumentCount' => '2' ), 'IMABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMABS', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMABS', 'argumentCount' => '1' ), 'IMAGINARY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMAGINARY', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMAGINARY', 'argumentCount' => '1' ), 'IMARGUMENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMARGUMENT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMARGUMENT', 'argumentCount' => '1' ), 'IMCONJUGATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMCONJUGATE', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMCONJUGATE', 'argumentCount' => '1' ), 'IMCOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMCOS', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMCOS', 'argumentCount' => '1' ), 'IMDIV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMDIV', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMDIV', 'argumentCount' => '2' ), 'IMEXP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMEXP', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMEXP', 'argumentCount' => '1' ), 'IMLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMLN', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLN', 'argumentCount' => '1' ), 'IMLOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMLOG10', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG10', 'argumentCount' => '1' ), 'IMLOG2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMLOG2', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG2', 'argumentCount' => '1' ), 'IMPOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMPOWER', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMPOWER', 'argumentCount' => '2' ), 'IMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMPRODUCT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMPRODUCT', 'argumentCount' => '1+' ), 'IMREAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMREAL', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMREAL', 'argumentCount' => '1' ), 'IMSIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMSIN', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSIN', 'argumentCount' => '1' ), 'IMSQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMSQRT', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSQRT', 'argumentCount' => '1' ), 'IMSUB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMSUB', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUB', 'argumentCount' => '2' ), 'IMSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::IMSUM', + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUM', 'argumentCount' => '1+' ), 'INDEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::INDEX', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::INDEX', 'argumentCount' => '1-4' ), 'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::INDIRECT', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::INDIRECT', 'argumentCount' => '1,2', 'passCellReference'=> true ), @@ -868,23 +877,23 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'INT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::INTVALUE', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::INT', 'argumentCount' => '1' ), 'INTERCEPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::INTERCEPT', + 'functionCall' => 'PHPExcel_Calculation_Statistical::INTERCEPT', 'argumentCount' => '2' ), 'INTRATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::INTRATE', + 'functionCall' => 'PHPExcel_Calculation_Financial::INTRATE', 'argumentCount' => '4,5' ), 'IPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::IPMT', + 'functionCall' => 'PHPExcel_Calculation_Financial::IPMT', 'argumentCount' => '4-6' ), 'IRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::IRR', + 'functionCall' => 'PHPExcel_Calculation_Financial::IRR', 'argumentCount' => '1,2' ), 'ISBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -924,7 +933,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'ISPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::ISPMT', + 'functionCall' => 'PHPExcel_Calculation_Financial::ISPMT', 'argumentCount' => '4' ), 'ISREF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -940,35 +949,35 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'KURT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::KURT', + 'functionCall' => 'PHPExcel_Calculation_Statistical::KURT', 'argumentCount' => '1+' ), 'LARGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LARGE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::LARGE', 'argumentCount' => '2' ), 'LCM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::LCM', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::LCM', 'argumentCount' => '1+' ), 'LEFT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::LEFT', + 'functionCall' => 'PHPExcel_Calculation_TextData::LEFT', 'argumentCount' => '1,2' ), 'LEFTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::LEFT', + 'functionCall' => 'PHPExcel_Calculation_TextData::LEFT', 'argumentCount' => '1,2' ), 'LEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::STRINGLENGTH', + 'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH', 'argumentCount' => '1' ), 'LENB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::STRINGLENGTH', + 'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH', 'argumentCount' => '1' ), 'LINEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LINEST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::LINEST', 'argumentCount' => '1-4' ), 'LN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -976,7 +985,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'LOG' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOG_BASE', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::LOG_BASE', 'argumentCount' => '1,2' ), 'LOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -984,43 +993,43 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'LOGEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGEST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGEST', 'argumentCount' => '1-4' ), 'LOGINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGINV', 'argumentCount' => '3' ), 'LOGNORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGNORMDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGNORMDIST', 'argumentCount' => '3' ), 'LOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOOKUP', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::LOOKUP', 'argumentCount' => '2,3' ), 'LOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOWERCASE', + 'functionCall' => 'PHPExcel_Calculation_TextData::LOWERCASE', 'argumentCount' => '1' ), 'MATCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::MATCH', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::MATCH', 'argumentCount' => '2,3' ), 'MAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MAX', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAX', 'argumentCount' => '1+' ), 'MAXA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MAXA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAXA', 'argumentCount' => '1+' ), 'MAXIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAXIF', 'argumentCount' => '2+' ), 'MDETERM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MDETERM', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MDETERM', 'argumentCount' => '1' ), 'MDURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1028,7 +1037,7 @@ class PHPExcel_Calculation { 'argumentCount' => '5,6' ), 'MEDIAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MEDIAN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MEDIAN', 'argumentCount' => '1+' ), 'MEDIANIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -1036,59 +1045,59 @@ class PHPExcel_Calculation { 'argumentCount' => '2+' ), 'MID' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::MID', + 'functionCall' => 'PHPExcel_Calculation_TextData::MID', 'argumentCount' => '3' ), 'MIDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::MID', + 'functionCall' => 'PHPExcel_Calculation_TextData::MID', 'argumentCount' => '3' ), 'MIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MIN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MIN', 'argumentCount' => '1+' ), 'MINA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MINA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MINA', 'argumentCount' => '1+' ), 'MINIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MINIF', 'argumentCount' => '2+' ), 'MINUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::MINUTEOFHOUR', + 'functionCall' => 'PHPExcel_Calculation_DateTime::MINUTEOFHOUR', 'argumentCount' => '1' ), 'MINVERSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MINVERSE', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MINVERSE', 'argumentCount' => '1' ), 'MIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MIRR', + 'functionCall' => 'PHPExcel_Calculation_Financial::MIRR', 'argumentCount' => '3' ), 'MMULT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MMULT', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MMULT', 'argumentCount' => '2' ), 'MOD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MOD', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MOD', 'argumentCount' => '2' ), 'MODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::MODE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::MODE', 'argumentCount' => '1+' ), 'MONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::MONTHOFYEAR', + 'functionCall' => 'PHPExcel_Calculation_DateTime::MONTHOFYEAR', 'argumentCount' => '1' ), 'MROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MROUND', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MROUND', 'argumentCount' => '2' ), 'MULTINOMIAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::MULTINOMIAL', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MULTINOMIAL', 'argumentCount' => '1+' ), 'N' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, @@ -1100,63 +1109,63 @@ class PHPExcel_Calculation { 'argumentCount' => '0' ), 'NEGBINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NEGBINOMDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::NEGBINOMDIST', 'argumentCount' => '3' ), 'NETWORKDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::NETWORKDAYS', + 'functionCall' => 'PHPExcel_Calculation_DateTime::NETWORKDAYS', 'argumentCount' => '2+' ), 'NOMINAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NOMINAL', + 'functionCall' => 'PHPExcel_Calculation_Financial::NOMINAL', 'argumentCount' => '2' ), 'NORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NORMDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMDIST', 'argumentCount' => '4' ), 'NORMINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NORMINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMINV', 'argumentCount' => '3' ), 'NORMSDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NORMSDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSDIST', 'argumentCount' => '1' ), 'NORMSINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NORMSINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSINV', 'argumentCount' => '1' ), 'NOT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_NOT', + 'functionCall' => 'PHPExcel_Calculation_Logical::NOT', 'argumentCount' => '1' ), 'NOW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DATETIMENOW', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATETIMENOW', 'argumentCount' => '0' ), 'NPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NPER', + 'functionCall' => 'PHPExcel_Calculation_Financial::NPER', 'argumentCount' => '3-5' ), 'NPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::NPV', + 'functionCall' => 'PHPExcel_Calculation_Financial::NPV', 'argumentCount' => '2+' ), 'OCT2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::OCTTOBIN', + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOBIN', 'argumentCount' => '1,2' ), 'OCT2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::OCTTODEC', + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTODEC', 'argumentCount' => '1' ), 'OCT2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, - 'functionCall' => 'PHPExcel_Calculation_Functions::OCTTOHEX', + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOHEX', 'argumentCount' => '1,2' ), 'ODD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::ODD', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ODD', 'argumentCount' => '1' ), 'ODDFPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1176,29 +1185,29 @@ class PHPExcel_Calculation { 'argumentCount' => '7,8' ), 'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::OFFSET', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::OFFSET', 'argumentCount' => '3,5', 'passCellReference'=> true, 'passByReference' => array(true) ), 'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_OR', + 'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_OR', 'argumentCount' => '1+' ), 'PEARSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::CORREL', + 'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL', 'argumentCount' => '2' ), 'PERCENTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PERCENTILE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTILE', 'argumentCount' => '2' ), 'PERCENTRANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PERCENTRANK', + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTRANK', 'argumentCount' => '2,3' ), 'PERMUT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PERMUT', + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERMUT', 'argumentCount' => '2' ), 'PHONETIC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, @@ -1210,31 +1219,31 @@ class PHPExcel_Calculation { 'argumentCount' => '0' ), 'PMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PMT', + 'functionCall' => 'PHPExcel_Calculation_Financial::PMT', 'argumentCount' => '3-5' ), 'POISSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::POISSON', + 'functionCall' => 'PHPExcel_Calculation_Statistical::POISSON', 'argumentCount' => '3' ), 'POWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::POWER', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::POWER', 'argumentCount' => '2' ), 'PPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PPMT', + 'functionCall' => 'PHPExcel_Calculation_Financial::PPMT', 'argumentCount' => '4-6' ), 'PRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PRICE', + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICE', 'argumentCount' => '6,7' ), 'PRICEDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PRICEDISC', + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICEDISC', 'argumentCount' => '4,5' ), 'PRICEMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PRICEMAT', + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICEMAT', 'argumentCount' => '5,6' ), 'PROB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -1242,23 +1251,23 @@ class PHPExcel_Calculation { 'argumentCount' => '3,4' ), 'PRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::PRODUCT', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::PRODUCT', 'argumentCount' => '1+' ), 'PROPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::PROPERCASE', + 'functionCall' => 'PHPExcel_Calculation_TextData::PROPERCASE', 'argumentCount' => '1' ), 'PV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::PV', + 'functionCall' => 'PHPExcel_Calculation_Financial::PV', 'argumentCount' => '3-5' ), 'QUARTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::QUARTILE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::QUARTILE', 'argumentCount' => '2' ), 'QUOTIENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::QUOTIENT', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::QUOTIENT', 'argumentCount' => '2' ), 'RADIANS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1266,31 +1275,31 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'RAND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::RAND', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND', 'argumentCount' => '0' ), 'RANDBETWEEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::RAND', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND', 'argumentCount' => '2' ), 'RANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::RANK', + 'functionCall' => 'PHPExcel_Calculation_Statistical::RANK', 'argumentCount' => '2,3' ), 'RATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::RATE', + 'functionCall' => 'PHPExcel_Calculation_Financial::RATE', 'argumentCount' => '3-6' ), 'RECEIVED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::RECEIVED', + 'functionCall' => 'PHPExcel_Calculation_Financial::RECEIVED', 'argumentCount' => '4-5' ), 'REPLACE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::REPLACE', + 'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE', 'argumentCount' => '4' ), 'REPLACEB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::REPLACE', + 'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE', 'argumentCount' => '4' ), 'REPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, @@ -1298,15 +1307,15 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'RIGHT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::RIGHT', + 'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT', 'argumentCount' => '1,2' ), 'RIGHTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::RIGHT', + 'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT', 'argumentCount' => '1,2' ), 'ROMAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::ROMAN', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROMAN', 'argumentCount' => '1,2' ), 'ROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1314,24 +1323,24 @@ class PHPExcel_Calculation { 'argumentCount' => '2' ), 'ROUNDDOWN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::ROUNDDOWN', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDDOWN', 'argumentCount' => '2' ), 'ROUNDUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::ROUNDUP', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDUP', 'argumentCount' => '2' ), 'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::ROW', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROW', 'argumentCount' => '-1', 'passByReference' => array(true) ), 'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::ROWS', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROWS', 'argumentCount' => '1' ), 'RSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::RSQ', + 'functionCall' => 'PHPExcel_Calculation_Statistical::RSQ', 'argumentCount' => '2' ), 'RTD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, @@ -1339,23 +1348,23 @@ class PHPExcel_Calculation { 'argumentCount' => '1+' ), 'SEARCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHINSENSITIVE', + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE', 'argumentCount' => '2,3' ), 'SEARCHB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::SEARCHINSENSITIVE', + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE', 'argumentCount' => '2,3' ), 'SECOND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::SECONDOFMINUTE', + 'functionCall' => 'PHPExcel_Calculation_DateTime::SECONDOFMINUTE', 'argumentCount' => '1' ), 'SERIESSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SERIESSUM', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SERIESSUM', 'argumentCount' => '4' ), 'SIGN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SIGN', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SIGN', 'argumentCount' => '1' ), 'SIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1367,19 +1376,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'SKEW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::SKEW', + 'functionCall' => 'PHPExcel_Calculation_Statistical::SKEW', 'argumentCount' => '1+' ), 'SLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::SLN', + 'functionCall' => 'PHPExcel_Calculation_Financial::SLN', 'argumentCount' => '3' ), 'SLOPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::SLOPE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::SLOPE', 'argumentCount' => '2' ), 'SMALL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::SMALL', + 'functionCall' => 'PHPExcel_Calculation_Statistical::SMALL', 'argumentCount' => '2' ), 'SQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1387,47 +1396,47 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'SQRTPI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SQRTPI', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SQRTPI', 'argumentCount' => '1' ), 'STANDARDIZE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STANDARDIZE', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STANDARDIZE', 'argumentCount' => '3' ), 'STDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STDEV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEV', 'argumentCount' => '1+' ), 'STDEVA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STDEVA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVA', 'argumentCount' => '1+' ), 'STDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STDEVP', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVP', 'argumentCount' => '1+' ), 'STDEVPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STDEVPA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVPA', 'argumentCount' => '1+' ), 'STEYX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::STEYX', + 'functionCall' => 'PHPExcel_Calculation_Statistical::STEYX', 'argumentCount' => '2' ), 'SUBSTITUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUBSTITUTE', + 'functionCall' => 'PHPExcel_Calculation_TextData::SUBSTITUTE', 'argumentCount' => '3,4' ), 'SUBTOTAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUBTOTAL', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUBTOTAL', 'argumentCount' => '2+' ), 'SUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUM', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUM', 'argumentCount' => '1+' ), 'SUMIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMIF', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMIF', 'argumentCount' => '2,3' ), 'SUMIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1435,31 +1444,31 @@ class PHPExcel_Calculation { 'argumentCount' => '?' ), 'SUMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMPRODUCT', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMPRODUCT', 'argumentCount' => '1+' ), 'SUMSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMSQ', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMSQ', 'argumentCount' => '1+' ), 'SUMX2MY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMX2MY2', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2MY2', 'argumentCount' => '2' ), 'SUMX2PY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMX2PY2', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2PY2', 'argumentCount' => '2' ), 'SUMXMY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::SUMXMY2', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMXMY2', 'argumentCount' => '2' ), 'SYD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::SYD', + 'functionCall' => 'PHPExcel_Calculation_Financial::SYD', 'argumentCount' => '4' ), 'T' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::RETURNSTRING', + 'functionCall' => 'PHPExcel_Calculation_TextData::RETURNSTRING', 'argumentCount' => '1' ), 'TAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, @@ -1471,63 +1480,63 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'TBILLEQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TBILLEQ', + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLEQ', 'argumentCount' => '3' ), 'TBILLPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TBILLPRICE', + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLPRICE', 'argumentCount' => '3' ), 'TBILLYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TBILLYIELD', + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLYIELD', 'argumentCount' => '3' ), 'TDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TDIST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::TDIST', 'argumentCount' => '3' ), 'TEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::TEXTFORMAT', + 'functionCall' => 'PHPExcel_Calculation_TextData::TEXTFORMAT', 'argumentCount' => '2' ), 'TIME' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::TIME', + 'functionCall' => 'PHPExcel_Calculation_DateTime::TIME', 'argumentCount' => '3' ), 'TIMEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::TIMEVALUE', + 'functionCall' => 'PHPExcel_Calculation_DateTime::TIMEVALUE', 'argumentCount' => '1' ), 'TINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TINV', + 'functionCall' => 'PHPExcel_Calculation_Statistical::TINV', 'argumentCount' => '2' ), 'TODAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DATENOW', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATENOW', 'argumentCount' => '0' ), 'TRANSPOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::TRANSPOSE', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::TRANSPOSE', 'argumentCount' => '1' ), 'TREND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TREND', + 'functionCall' => 'PHPExcel_Calculation_Statistical::TREND', 'argumentCount' => '1-4' ), 'TRIM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::TRIMSPACES', + 'functionCall' => 'PHPExcel_Calculation_TextData::TRIMSPACES', 'argumentCount' => '1' ), 'TRIMMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::TRIMMEAN', + 'functionCall' => 'PHPExcel_Calculation_Statistical::TRIMMEAN', 'argumentCount' => '2' ), 'TRUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::LOGICAL_TRUE', + 'functionCall' => 'PHPExcel_Calculation_Logical::TRUE', 'argumentCount' => '0' ), 'TRUNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, - 'functionCall' => 'PHPExcel_Calculation_Functions::TRUNC', + 'functionCall' => 'PHPExcel_Calculation_MathTrig::TRUNC', 'argumentCount' => '1,2' ), 'TTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, @@ -1539,7 +1548,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'UPPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, - 'functionCall' => 'PHPExcel_Calculation_Functions::UPPERCASE', + 'functionCall' => 'PHPExcel_Calculation_TextData::UPPERCASE', 'argumentCount' => '1' ), 'USDOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1551,19 +1560,19 @@ class PHPExcel_Calculation { 'argumentCount' => '1' ), 'VAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::VARFunc', + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARFunc', 'argumentCount' => '1+' ), 'VARA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::VARA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARA', 'argumentCount' => '1+' ), 'VARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::VARP', + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARP', 'argumentCount' => '1+' ), 'VARPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::VARPA', + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARPA', 'argumentCount' => '1+' ), 'VDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1575,39 +1584,39 @@ class PHPExcel_Calculation { 'argumentCount' => '0' ), 'VLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::VLOOKUP', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::VLOOKUP', 'argumentCount' => '3,4' ), 'WEEKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::DAYOFWEEK', + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFWEEK', 'argumentCount' => '1,2' ), 'WEEKNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::WEEKOFYEAR', + 'functionCall' => 'PHPExcel_Calculation_DateTime::WEEKOFYEAR', 'argumentCount' => '1,2' ), 'WEIBULL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::WEIBULL', + 'functionCall' => 'PHPExcel_Calculation_Statistical::WEIBULL', 'argumentCount' => '4' ), 'WORKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::WORKDAY', + 'functionCall' => 'PHPExcel_Calculation_DateTime::WORKDAY', 'argumentCount' => '2+' ), 'XIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::XIRR', + 'functionCall' => 'PHPExcel_Calculation_Financial::XIRR', 'argumentCount' => '2,3' ), 'XNPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::XNPV', + 'functionCall' => 'PHPExcel_Calculation_Financial::XNPV', 'argumentCount' => '3' ), 'YEAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::YEAR', + 'functionCall' => 'PHPExcel_Calculation_DateTime::YEAR', 'argumentCount' => '1' ), 'YEARFRAC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, - 'functionCall' => 'PHPExcel_Calculation_Functions::YEARFRAC', + 'functionCall' => 'PHPExcel_Calculation_DateTime::YEARFRAC', 'argumentCount' => '2,3' ), 'YIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, @@ -1615,15 +1624,15 @@ class PHPExcel_Calculation { 'argumentCount' => '6,7' ), 'YIELDDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::YIELDDISC', + 'functionCall' => 'PHPExcel_Calculation_Financial::YIELDDISC', 'argumentCount' => '4,5' ), 'YIELDMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::YIELDMAT', + 'functionCall' => 'PHPExcel_Calculation_Financial::YIELDMAT', 'argumentCount' => '5,6' ), 'ZTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, - 'functionCall' => 'PHPExcel_Calculation_Functions::ZTEST', + 'functionCall' => 'PHPExcel_Calculation_Statistical::ZTEST', 'argumentCount' => '2-3' ) ); @@ -2141,7 +2150,7 @@ class PHPExcel_Calculation { // We return an empty array if not $formula = trim($formula); if ((!isset($formula{0})) || ($formula{0} != '=')) return array(); - $formula = trim(substr($formula,1)); + $formula = ltrim(substr($formula,1)); if (!isset($formula{0})) return array(); // Parse the formula and return the token stack @@ -2196,7 +2205,7 @@ class PHPExcel_Calculation { // We simply return the "cell value" (formula) if not $formula = trim($formula); if ($formula{0} != '=') return self::_wrapResult($formula); - $formula = trim(substr($formula,1)); + $formula = ltrim(substr($formula,1)); if (!isset($formula{0})) return self::_wrapResult($formula); $wsTitle = "\x00Wrk"; @@ -2215,7 +2224,7 @@ class PHPExcel_Calculation { // echo 'Value is in cache
'; $this->_writeDebug('Testing cache value for cell '.$cellID); // Is cache still valid? - if ((time() + microtime(true)) - self::$_calculationCache[$wsTitle][$cellID]['time'] < self::$_calculationCacheExpirationTime) { + if ((microtime(true) - self::$_calculationCache[$wsTitle][$cellID]['time']) < self::$_calculationCacheExpirationTime) { // echo 'Cache time is still valid
'; $this->_writeDebug('Retrieving value for '.$cellID.' from cache'); // Return the cached result @@ -2262,7 +2271,7 @@ class PHPExcel_Calculation { // Save to calculation cache if (!is_null($cellID)) { if (self::$_calculationCacheEnabled) { - self::$_calculationCache[$wsTitle][$cellID]['time'] = (time() + microtime(true)); + self::$_calculationCache[$wsTitle][$cellID]['time'] = microtime(true); self::$_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; } } @@ -2565,7 +2574,7 @@ class PHPExcel_Calculation { ); // Comparison (Boolean) Operators // These operators work on two values, but always return a boolean result - $comparisonOperators = array('>', '<', '=', '>=', '<=', '<>'); + $comparisonOperators = array('>' => true, '<' => true, '=' => true, '>=' => true, '<=' => true, '<>' => true); // Operator Precedence // This list includes all valid operators, whether binary (including boolean) or unary (such as %) @@ -2604,14 +2613,14 @@ class PHPExcel_Calculation { // echo 'Assessing Expression '.substr($formula, $index).'
'; $opCharacter = $formula{$index}; // Get the first character of the value at the current index position // echo 'Initial character of expression block is '.$opCharacter.'
'; - if ((in_array($opCharacter, $comparisonOperators)) && (strlen($formula) > $index) && (in_array($formula{$index+1}, $comparisonOperators))) { + if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) { $opCharacter .= $formula{++$index}; // echo 'Initial character of expression block is comparison operator '.$opCharacter.'
'; } // Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match); -// echo '$isOperandOrFunction is '.(($isOperandOrFunction)?'True':'False').'
'; +// echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').'
'; if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? // echo 'Element is a Negation operator
'; @@ -2627,11 +2636,11 @@ class PHPExcel_Calculation { } elseif (($opCharacter == '~') && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde, because it's legal return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression - } elseif ((in_array($opCharacter, self::$_operators) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? + } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? // echo 'Element with value '.$opCharacter.' is an Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2['value'], self::$_operators) && + isset(self::$_operators[$o2['value']]) && @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } @@ -2772,8 +2781,8 @@ class PHPExcel_Calculation { } } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) { // echo 'Element '.$val.' is a Cell reference
'; -// Watch for this case-change when modifying to allow cell references in different worksheets... -// Should only be applied to the actual cell column, not the worksheet name + // Watch for this case-change when modifying to allow cell references in different worksheets... + // Should only be applied to the actual cell column, not the worksheet name // If the last entry on the stack was a : operator, then we have a cell range reference $testPrevOp = $stack->last(1); @@ -2787,6 +2796,8 @@ class PHPExcel_Calculation { if ($startMatches[2] > '') { $val = $startMatches[2].'!'.$val; } + } else { + return $this->_raiseFormulaError("3D Range references are not yet supported"); } } @@ -2861,7 +2872,7 @@ class PHPExcel_Calculation { } else { return $this->_raiseFormulaError("Formula Error: Unexpected ')'"); } - } elseif (in_array($opCharacter, self::$_operators) && !$expectingOperator) { + } elseif (isset(self::$_operators[$opCharacter]) && !$expectingOperator) { return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'"); } else { // I don't even want to know what you did to get here return $this->_raiseFormulaError("Formula Error: An unexpected error occured"); @@ -2870,7 +2881,7 @@ class PHPExcel_Calculation { if ($index == strlen($formula)) { // Did we end with an operator?. // Only valid for the % unary operator - if ((in_array($opCharacter, self::$_operators)) && ($opCharacter != '%')) { + if ((isset(self::$_operators[$opCharacter])) && ($opCharacter != '%')) { return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands"); } else { break; @@ -2892,7 +2903,7 @@ class PHPExcel_Calculation { // echo 'Element is an Intersect Operator
'; while($stack->count() > 0 && ($o2 = $stack->last()) && - in_array($o2['value'], self::$_operators) && + isset(self::$_operators[$o2['value']]) && @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } @@ -2926,7 +2937,7 @@ class PHPExcel_Calculation { $token = $tokenData['value']; // echo 'Token is '.$token.'
'; // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack - if (in_array($token, self::$_binaryOperators, true)) { + if (isset(self::$_binaryOperators[$token])) { // echo 'Token is a binary operator
'; // We must have two operands, error if we don't if (is_null($operand2Data = $stack->pop())) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); @@ -3049,11 +3060,11 @@ class PHPExcel_Calculation { case '|' : // Intersect $rowIntersect = array_intersect_key($operand1,$operand2); $cellIntersect = $oCol = $oRow = array(); - foreach(array_keys($rowIntersect) as $col) { - $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1; - $cellIntersect[$col] = array_intersect_key($operand1[$col],$operand2[$col]); - foreach($cellIntersect[$col] as $row => $data) { - $oRow[] = $row; + foreach(array_keys($rowIntersect) as $row) { + $oRow[] = $row; + foreach($rowIntersect[$row] as $col => $data) { + $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1; + $cellIntersect[$row] = array_intersect_key($operand1[$row],$operand2[$row]); } } $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); @@ -3433,35 +3444,40 @@ class PHPExcel_Calculation { $result = '#VALUE!'; } } else { - // If we're dealing with non-matrix operations, execute the necessary operation - switch ($operation) { - // Addition - case '+': - $result = $operand1+$operand2; - break; - // Subtraction - case '-': - $result = $operand1-$operand2; - break; - // Multiplication - case '*': - $result = $operand1*$operand2; - break; - // Division - case '/': - if ($operand2 == 0) { - // Trap for Divide by Zero error - $stack->push('Value','#DIV/0!'); - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails('#DIV/0!')); - return false; - } else { - $result = $operand1/$operand2; - } - break; - // Power - case '^': - $result = pow($operand1,$operand2); - break; + if ((PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) && + ((is_string($operand1) && !is_numeric($operand1)) || (is_string($operand2) && !is_numeric($operand2)))) { + $result = PHPExcel_Calculation_Functions::VALUE(); + } else { + // If we're dealing with non-matrix operations, execute the necessary operation + switch ($operation) { + // Addition + case '+': + $result = $operand1+$operand2; + break; + // Subtraction + case '-': + $result = $operand1-$operand2; + break; + // Multiplication + case '*': + $result = $operand1*$operand2; + break; + // Division + case '/': + if ($operand2 == 0) { + // Trap for Divide by Zero error + $stack->push('Value','#DIV/0!'); + $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails('#DIV/0!')); + return false; + } else { + $result = $operand1/$operand2; + } + break; + // Power + case '^': + $result = pow($operand1,$operand2); + break; + } } } diff --git a/Classes/PHPExcel/Calculation/Functions.php b/Classes/PHPExcel/Calculation/Functions.php index b7042a55..6886fd55 100644 --- a/Classes/PHPExcel/Calculation/Functions.php +++ b/Classes/PHPExcel/Calculation/Functions.php @@ -36,36 +36,18 @@ if (!defined('PHPEXCEL_ROOT')) { } -/** EPS */ -define('EPS', 2.22e-16); - /** MAX_VALUE */ define('MAX_VALUE', 1.2e308); -/** LOG_GAMMA_X_MAX_VALUE */ -define('LOG_GAMMA_X_MAX_VALUE', 2.55e305); - -/** SQRT2PI */ -define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099); - /** 2 / PI */ define('M_2DIVPI', 0.63661977236758134307553505349006); -/** XMININ */ -define('XMININ', 2.23e-308); - /** MAX_ITERATIONS */ define('MAX_ITERATIONS', 256); -/** FINANCIAL_MAX_ITERATIONS */ -define('FINANCIAL_MAX_ITERATIONS', 128); /** PRECISION */ define('PRECISION', 8.88E-016); -/** FINANCIAL_PRECISION */ -define('FINANCIAL_PRECISION', 1.0e-08); -/** EULER */ -define('EULER', 2.71828182845904523536); $savedPrecision = ini_get('precision'); if ($savedPrecision < 16) { @@ -73,11 +55,6 @@ if ($savedPrecision < 16) { } -/** Matrix */ -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; -require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/trendClass.php'; - - /** * PHPExcel_Calculation_Functions * @@ -103,7 +80,7 @@ class PHPExcel_Calculation_Functions { * @access private * @var string */ - private static $compatibilityMode = self::COMPATIBILITY_EXCEL; + protected static $compatibilityMode = self::COMPATIBILITY_EXCEL; /** * Data Type to use when returning date values @@ -111,7 +88,7 @@ class PHPExcel_Calculation_Functions { * @access private * @var string */ - private static $ReturnDateType = self::RETURNDATE_EXCEL; + protected static $ReturnDateType = self::RETURNDATE_EXCEL; /** * List of error codes @@ -119,15 +96,15 @@ class PHPExcel_Calculation_Functions { * @access private * @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' - ); + protected static $_errorCodes = array( 'null' => '#NULL!', + 'divisionbyzero' => '#DIV/0!', + 'value' => '#VALUE!', + 'reference' => '#REF!', + 'name' => '#NAME?', + 'num' => '#NUM!', + 'na' => '#N/A', + 'gettingdata' => '#GETTING_DATA' + ); /** @@ -220,6 +197,18 @@ class PHPExcel_Calculation_Functions { } // function DUMMY() + /** + * DIV0 + * + * @access public + * @category Error Returns + * @return string #Not Yet Implemented + */ + public static function DIV0() { + return self::$_errorCodes['divisionbyzero']; + } // function DIV0() + + /** * NA * @@ -239,7 +228,7 @@ class PHPExcel_Calculation_Functions { /** - * NAN + * NaN * * Returns the error value #NUM! * @@ -249,7 +238,7 @@ class PHPExcel_Calculation_Functions { */ public static function NaN() { return self::$_errorCodes['num']; - } // function NAN() + } // function NaN() /** @@ -280,6 +269,20 @@ class PHPExcel_Calculation_Functions { } // function REF() + /** + * NULL + * + * Returns the error value #NULL! + * + * @access public + * @category Error Returns + * @return string #REF! + */ + public static function NULL() { + return self::$_errorCodes['null']; + } // function NULL() + + /** * VALUE * @@ -294,733 +297,23 @@ class PHPExcel_Calculation_Functions { } // function VALUE() - private static function isMatrixValue($idx) { + public static function isMatrixValue($idx) { return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0)); } - private static function isValue($idx) { + public static function isValue($idx) { return (substr_count($idx,'.') == 0); } - private static function isCellValue($idx) { + public static function isCellValue($idx) { return (substr_count($idx,'.') > 1); } - /** - * LOGICAL_AND - * - * Returns boolean TRUE if all its arguments are TRUE; returns FALSE if one or more argument is FALSE. - * - * Excel Function: - * =AND(logical1[,logical2[, ...]]) - * - * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays - * or references that contain logical values. - * - * Boolean 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, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value - * - * @access public - * @category Logical Functions - * @param mixed $arg,... Data values - * @return boolean The logical AND of the arguments. - */ - 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; - } elseif ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue = $returnValue && ($arg != 0); - } elseif (is_string($arg)) { - $arg = strtoupper($arg); - if ($arg == 'TRUE') { - $arg = 1; - } elseif ($arg == 'FALSE') { - $arg = 0; - } else { - return self::$_errorCodes['value']; - } - $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. - * - * Excel Function: - * =OR(logical1[,logical2[, ...]]) - * - * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays - * or references that contain logical values. - * - * Boolean 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, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value - * - * @access public - * @category Logical Functions - * @param mixed $arg,... Data values - * @return boolean The logical OR of the arguments. - */ - 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; - } elseif ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue = $returnValue || ($arg != 0); - } elseif (is_string($arg)) { - $arg = strtoupper($arg); - if ($arg == 'TRUE') { - $arg = 1; - } elseif ($arg == 'FALSE') { - $arg = 0; - } else { - return self::$_errorCodes['value']; - } - $returnValue = $returnValue || ($arg != 0); - } - ++$argCount; - } - - // Return - if ($argCount == 0) { - return self::$_errorCodes['value']; - } - return $returnValue; - } // function LOGICAL_OR() - - - /** - * LOGICAL_FALSE - * - * Returns the boolean FALSE. - * - * Excel Function: - * =FALSE() - * - * @access public - * @category Logical Functions - * @return boolean False - */ - public static function LOGICAL_FALSE() { - return False; - } // function LOGICAL_FALSE() - - - /** - * LOGICAL_TRUE - * - * Returns the boolean TRUE. - * - * Excel Function: - * =TRUE() - * - * @access public - * @category Logical Functions - * @return boolean True - */ - public static function LOGICAL_TRUE() { - return True; - } // function LOGICAL_TRUE() - - - /** - * LOGICAL_NOT - * - * Returns the boolean inverse of the argument. - * - * Excel Function: - * =NOT(logical) - * - * The argument must evaluate to a logical value such as TRUE or FALSE - * - * Boolean 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, the function returns a #VALUE! error, unless the string holds - * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value - * - * @access public - * @category Logical Functions - * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE - * @return boolean The boolean inverse of the argument. - */ - public static function LOGICAL_NOT($logical) { - $logical = self::flattenSingleValue($logical); - if (is_string($logical)) { - $logical = strtoupper($logical); - if ($logical == 'TRUE') { - return False; - } elseif ($logical == 'FALSE') { - return True; - } else { - return self::$_errorCodes['value']; - } - } - - return !$logical; - } // function LOGICAL_NOT() - - - /** - * STATEMENT_IF - * - * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE. - * - * Excel Function: - * =IF(condition[,returnIfTrue[,returnIfFalse]]) - * - * Condition is any value or expression that can be evaluated to TRUE or FALSE. - * For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100, - * the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE. - * This argument can use any comparison calculation operator. - * ReturnIfTrue is the value that is returned if condition evaluates to TRUE. - * For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE, - * then the IF function returns the text "Within budget" - * If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use - * the logical value TRUE for this argument. - * ReturnIfTrue can be another formula. - * ReturnIfFalse is the value that is returned if condition evaluates to FALSE. - * For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE, - * then the IF function returns the text "Over budget". - * If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned. - * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. - * ReturnIfFalse can be another formula. - * - * @access public - * @category Logical Functions - * @param mixed $condition Condition to evaluate - * @param mixed $returnIfTrue Value to return when condition is true - * @param mixed $returnIfFalse Optional value to return when condition is false - * @return mixed The value of returnIfTrue or returnIfFalse determined by condition - */ - public static function STATEMENT_IF($condition = true, $returnIfTrue = 0, $returnIfFalse = False) { - $condition = (is_null($condition)) ? True : (boolean) self::flattenSingleValue($condition); - $returnIfTrue = (is_null($returnIfTrue)) ? 0 : self::flattenSingleValue($returnIfTrue); - $returnIfFalse = (is_null($returnIfFalse)) ? False : self::flattenSingleValue($returnIfFalse); - - return ($condition ? $returnIfTrue : $returnIfFalse); - } // function STATEMENT_IF() - - - /** - * STATEMENT_IFERROR - * - * Excel Function: - * =IFERROR(testValue,errorpart) - * - * @access public - * @category Logical Functions - * @param mixed $testValue Value to check, is also the value returned when no error - * @param mixed $errorpart Value to return when testValue is an error condition - * @return mixed The value of errorpart or testValue determined by error condition - */ - public static function STATEMENT_IFERROR($testValue = '', $errorpart = '') { - $testValue = (is_null($testValue)) ? '' : self::flattenSingleValue($testValue); - $errorpart = (is_null($errorpart)) ? '' : self::flattenSingleValue($errorpart); - - return self::STATEMENT_IF(self::IS_ERROR($testValue), $errorpart, $testValue); - } // function STATEMENT_IFERROR() - - - /** - * HYPERLINK - * - * Excel Function: - * =HYPERLINK(linkURL,displayName) - * - * @access public - * @category Logical Functions - * @param string $linkURL Value to check, is also the value returned when no error - * @param string $displayName Value to return when testValue is an error condition - * @return mixed The value of errorpart or testValue determined by error condition - */ - public static function HYPERLINK($linkURL = '', $displayName = null, PHPExcel_Cell $pCell = null) { - $args = func_get_args(); - $pCell = array_pop($args); - - $linkURL = (is_null($linkURL)) ? '' : self::flattenSingleValue($linkURL); - $displayName = (is_null($displayName)) ? '' : self::flattenSingleValue($displayName); - - if ((!is_object($pCell)) || (trim($linkURL) == '')) { - return self::$_errorCodes['reference']; - } - - if ((is_object($displayName)) || trim($displayName) == '') { - $displayName = $linkURL; - } - - $pCell->getHyperlink()->setUrl($linkURL); - - return $displayName; - } // function HYPERLINK() - - - /** - * 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. - * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a - * point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between - * -pi and pi, excluding -pi. - * - * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard - * PHP atan2() function, so we need to reverse them here before calling the PHP atan() function. - * - * Excel Function: - * ATAN2(xCoordinate,yCoordinate) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param float $xCoordinate The x-coordinate of the point. - * @param float $yCoordinate The y-coordinate of the point. - * @return float The inverse tangent of the specified x- and y-coordinates. - */ - public static function REVERSE_ATAN2($xCoordinate, $yCoordinate) { - $xCoordinate = (float) self::flattenSingleValue($xCoordinate); - $yCoordinate = (float) self::flattenSingleValue($yCoordinate); - - if (($xCoordinate == 0) && ($yCoordinate == 0)) { - return self::$_errorCodes['divisionbyzero']; - } - - return atan2($yCoordinate, $xCoordinate); - } // function REVERSE_ATAN2() - - - /** - * LOG_BASE - * - * Returns the logarithm of a number to a specified base. The default base is 10. - * - * Excel Function: - * LOG(number[,base]) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param float $value The positive real number for which you want the logarithm - * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10. - * @return float - */ - public static function LOG_BASE($number, $base=10) { - $number = self::flattenSingleValue($number); - $base = (is_null($base)) ? 10 : (float) self::flattenSingleValue($base); - - return log($number, $base); - } // function LOG_BASE() - - - /** - * SUM - * - * SUM computes the sum of all the values and cells referenced in the argument list. - * - * Excel Function: - * SUM(value1[,value2[, ...]]) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @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 - * - * SUMSQ returns the sum of the squares of the arguments - * - * Excel Function: - * SUMSQ(value1[,value2[, ...]]) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function SUMSQ() { - // Return value - $returnValue = 0; - - // 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))) { - $returnValue += ($arg * $arg); - } - } - - // Return - return $returnValue; - } // function SUMSQ() - - - /** - * PRODUCT - * - * PRODUCT returns the product of all the values and cells referenced in the argument list. - * - * Excel Function: - * PRODUCT(value1[,value2[, ...]]) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function PRODUCT() { - // 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_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. - * - * Excel Function: - * QUOTIENT(value1[,value2[, ...]]) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function QUOTIENT() { - // 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_string($arg))) { - if (is_null($returnValue)) { - $returnValue = ($arg == 0) ? 0 : $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. - * - * Excel Function: - * MIN(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function MIN() { - // 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_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 - * - * Excel Function: - * MINA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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() - - - /** - * MINIF - * - * Returns the minimum value within a range of cells that contain numbers within the list of arguments - * - * Excel Function: - * MINIF(value1[,value2[, ...]],condition) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @param string $condition The criteria that defines which cells will be checked. - * @return float - */ - public static function MINIF($aArgs,$condition,$sumArgs = array()) { - // Return value - $returnValue = null; - - $aArgs = self::flattenArray($aArgs); - $sumArgs = self::flattenArray($sumArgs); - if (count($sumArgs) == 0) { - $sumArgs = $aArgs; - } - $condition = self::_ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } - $testCondition = '='.$arg.$condition; - if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if ((is_null($returnValue)) || ($arg < $returnValue)) { - $returnValue = $arg; - } - } - } - - // Return - return $returnValue; - } // function MINIF() - - - /** - * SMALL - * - * Returns the nth smallest value in a data set. You can use this function to - * select a value based on its relative standing. - * - * Excel Function: - * SMALL(value1[,value2[, ...]],entry) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param int $entry Position (ordered from the smallest) in the array or range of data to return - * @return float - */ - public static function SMALL() { - $aArgs = self::flattenArray(func_get_args()); - - // Calculate - $entry = array_pop($aArgs); - - if ((is_numeric($entry)) && (!is_string($entry))) { - $mArgs = array(); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $mArgs[] = $arg; - } - } - $count = self::COUNT($mArgs); - $entry = floor(--$entry); - if (($entry < 0) || ($entry >= $count) || ($count == 0)) { - return self::$_errorCodes['num']; - } - sort($mArgs); - return $mArgs[$entry]; - } - return self::$_errorCodes['value']; - } // function SMALL() - - - /** - * 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. - * - * Excel Function: - * MAX(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function MAX() { - // 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_string($arg))) { - if ((is_null($returnValue)) || ($arg > $returnValue)) { - $returnValue = $arg; - } - } - } - - // Return - if(is_null($returnValue)) { - return 0; - } - return $returnValue; - } // function MAX() - - - /** - * MAXA - * - * Returns the greatest value in a list of arguments, including numbers, text, and logical values - * - * Excel Function: - * MAXA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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; - } // function MAXA() - - - private static function _ifCondition($condition) { - $condition = self::flattenSingleValue($condition); + public static function _ifCondition($condition) { + $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } return '='.$condition; @@ -1032,4493 +325,6 @@ class PHPExcel_Calculation_Functions { } } // function _ifCondition() - /** - * MAXIF - * - * Counts the maximum value within a range of cells that contain numbers within the list of arguments - * - * Excel Function: - * MAXIF(value1[,value2[, ...]],condition) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @param string $condition The criteria that defines which cells will be checked. - * @return float - */ - public static function MAXIF($aArgs,$condition,$sumArgs = array()) { - // Return value - $returnValue = null; - - $aArgs = self::flattenArray($aArgs); - $sumArgs = self::flattenArray($sumArgs); - if (count($sumArgs) == 0) { - $sumArgs = $aArgs; - } - $condition = self::_ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } - $testCondition = '='.$arg.$condition; - if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if ((is_null($returnValue)) || ($arg > $returnValue)) { - $returnValue = $arg; - } - } - } - - // Return - return $returnValue; - } // function MAXIF() - - - /** - * LARGE - * - * Returns the nth largest value in a data set. You can use this function to - * select a value based on its relative standing. - * - * Excel Function: - * LARGE(value1[,value2[, ...]],entry) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param int $entry Position (ordered from the largest) in the array or range of data to return - * @return float - * - */ - public static function LARGE() { - $aArgs = self::flattenArray(func_get_args()); - - // Calculate - $entry = floor(array_pop($aArgs)); - - if ((is_numeric($entry)) && (!is_string($entry))) { - $mArgs = array(); - foreach ($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $mArgs[] = $arg; - } - } - $count = self::COUNT($mArgs); - $entry = floor(--$entry); - if (($entry < 0) || ($entry >= $count) || ($count == 0)) { - return self::$_errorCodes['num']; - } - rsort($mArgs); - return $mArgs[$entry]; - } - return self::$_errorCodes['value']; - } // function LARGE() - - - /** - * PERCENTILE - * - * Returns the nth percentile of values in a range.. - * - * Excel Function: - * PERCENTILE(value1[,value2[, ...]],entry) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param float $entry Percentile value in the range 0..1, inclusive. - * @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']; - } // function PERCENTILE() - - - /** - * QUARTILE - * - * Returns the quartile of a data set. - * - * Excel Function: - * QUARTILE(value1[,value2[, ...]],entry) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param int $entry Quartile value in the range 1..3, inclusive. - * @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']; - } // function QUARTILE() - - - /** - * COUNT - * - * Counts the number of cells that contain numbers within the list of arguments - * - * Excel Function: - * COUNT(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return int - */ - public static function COUNT() { - // Return value - $returnValue = 0; - - // Loop through arguments - $aArgs = self::flattenArrayIndexed(func_get_args()); - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { - $arg = (integer) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - ++$returnValue; - } - } - - // Return - return $returnValue; - } // function COUNT() - - - /** - * COUNTBLANK - * - * Counts the number of empty cells within the list of arguments - * - * Excel Function: - * COUNTBLANK(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return int - */ - public static function COUNTBLANK() { - // Return value - $returnValue = 0; - - // Loop through 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; - } // function COUNTBLANK() - - - /** - * COUNTA - * - * Counts the number of cells that are not empty within the list of arguments - * - * Excel Function: - * COUNTA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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; - } // function COUNTA() - - - /** - * COUNTIF - * - * Counts the number of cells that contain numbers within the list of arguments - * - * Excel Function: - * COUNTIF(value1[,value2[, ...]],condition) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param string $condition The criteria that defines which cells will be counted. - * @return int - */ - public static function COUNTIF($aArgs,$condition) { - // Return value - $returnValue = 0; - - $aArgs = self::flattenArray($aArgs); - $condition = self::_ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } - $testCondition = '='.$arg.$condition; - if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is it a value within our criteria - ++$returnValue; - } - } - - // Return - return $returnValue; - } // function COUNTIF() - - - /** - * SUMIF - * - * Counts the number of cells that contain numbers within the list of arguments - * - * Excel Function: - * SUMIF(value1[,value2[, ...]],condition) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @param string $condition The criteria that defines which cells will be summed. - * @return float - */ - public static function SUMIF($aArgs,$condition,$sumArgs = array()) { - // Return value - $returnValue = 0; - - $aArgs = self::flattenArray($aArgs); - $sumArgs = self::flattenArray($sumArgs); - if (count($sumArgs) == 0) { - $sumArgs = $aArgs; - } - $condition = self::_ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } - $testCondition = '='.$arg.$condition; - if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - // Is it a value within our criteria - $returnValue += $sumArgs[$key]; - } - } - - // Return - return $returnValue; - } // function SUMIF() - - - /** - * AVERAGE - * - * Returns the average (arithmetic mean) of the arguments - * - * Excel Function: - * AVERAGE(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function AVERAGE() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - $returnValue = $aCount = 0; - // Loop through arguments - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (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']; - } - } // function AVERAGE() - - - /** - * AVERAGEA - * - * Returns the average of its arguments, including numbers, text, and logical values - * - * Excel Function: - * AVERAGEA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function AVERAGEA() { - // Return value - $returnValue = null; - - // Loop through arguments - $aArgs = self::flattenArrayIndexed(func_get_args()); - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - (!self::isMatrixValue($k))) { - } else { - 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']; - } - } // function AVERAGEA() - - - /** - * AVERAGEIF - * - * Returns the average value from a range of cells that contain numbers within the list of arguments - * - * Excel Function: - * AVERAGEIF(value1[,value2[, ...]],condition) - * - * @access public - * @category Mathematical and Trigonometric Functions - * @param mixed $arg,... Data values - * @param string $condition The criteria that defines which cells will be checked. - * @return float - */ - public static function AVERAGEIF($aArgs,$condition,$averageArgs = array()) { - // Return value - $returnValue = 0; - - $aArgs = self::flattenArray($aArgs); - $averageArgs = self::flattenArray($averageArgs); - if (count($averageArgs) == 0) { - $averageArgs = $aArgs; - } - $condition = self::_ifCondition($condition); - // Loop through arguments - $aCount = 0; - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } - $testCondition = '='.$arg.$condition; - if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if ((is_null($returnValue)) || ($arg > $returnValue)) { - $returnValue += $arg; - ++$aCount; - } - } - } - - // Return - if ($aCount > 0) { - return $returnValue / $aCount; - } else { - return self::$_errorCodes['divisionbyzero']; - } - } // function AVERAGEIF() - - - /** - * MEDIAN - * - * Returns the median of the given numbers. The median is the number in the middle of a set of numbers. - * - * Excel Function: - * MEDIAN(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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; - } // function MEDIAN() - - - // - // 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']; - } // function _modeCalc() - - - /** - * MODE - * - * Returns the most frequently occurring, or repetitive, value in an array or range of data - * - * Excel Function: - * MODE(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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; - } // function MODE() - - - /** - * DEVSQ - * - * Returns the sum of squares of deviations of data points from their sample mean. - * - * Excel Function: - * DEVSQ(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function DEVSQ() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if ($aMean != self::$_errorCodes['divisionbyzero']) { - $aCount = -1; - foreach ($aArgs as $k => $arg) { - // Is it a numeric value? - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE))) { - $arg = (integer) $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(); - } // function DEVSQ() - - - /** - * 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. - * - * Excel Function: - * AVEDEV(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function AVEDEV() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if ($aMean != self::$_errorCodes['divisionbyzero']) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (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 - if ($aCount == 0) { - return self::$_errorCodes['divisionbyzero']; - } - return $returnValue / $aCount; - } - return self::$_errorCodes['num']; - } // function AVEDEV() - - - /** - * 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. - * - * Excel Function: - * GEOMEAN(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function GEOMEAN() { - $aArgs = self::flattenArray(func_get_args()); - - $aMean = self::PRODUCT($aArgs); - if (is_numeric($aMean) && ($aMean > 0)) { - $aCount = self::COUNT($aArgs) ; - if (self::MIN($aArgs) > 0) { - return pow($aMean, (1 / $aCount)); - } - } - return self::$_errorCodes['num']; - } // GEOMEAN() - - - /** - * HARMEAN - * - * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the - * arithmetic mean of reciprocals. - * - * Excel Function: - * HARMEAN(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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; - } - } // function HARMEAN() - - - /** - * 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. - * - * Excel Function: - * TRIMEAN(value1[,value2[, ...]],$discard) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @param float $discard 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']; - } // function TRIMMEAN() - - - /** - * 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). - * - * Excel Function: - * STDEV(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function STDEV() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if (!is_null($aMean)) { - $aCount = -1; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (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 = 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']; - } // function STDEV() - - - /** - * STDEVA - * - * Estimates standard deviation based on a sample, including numbers, text, and logical values - * - * Excel Function: - * STDEVA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function STDEVA() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGEA($aArgs); - if (!is_null($aMean)) { - $aCount = -1; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - (!self::isMatrixValue($k))) { - } else { - // 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']; - } // function STDEVA() - - - /** - * STDEVP - * - * Calculates standard deviation based on the entire population - * - * Excel Function: - * STDEVP(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function STDEVP() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGE($aArgs); - if (!is_null($aMean)) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!self::isCellValue($k)) || (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 = 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']; - } // function STDEVP() - - - /** - * STDEVPA - * - * Calculates standard deviation based on the entire population, including numbers, text, and logical values - * - * Excel Function: - * STDEVPA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function STDEVPA() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - - // Return value - $returnValue = null; - - $aMean = self::AVERAGEA($aArgs); - if (!is_null($aMean)) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - (!self::isMatrixValue($k))) { - } else { - // 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']; - } // function STDEVPA() - - - /** - * VARFunc - * - * Estimates variance based on a sample. - * - * Excel Function: - * VAR(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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) { - if (is_bool($arg)) { $arg = (integer) $arg; } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - - // Return - if ($aCount > 1) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); - } - return $returnValue; - } // function VARFunc() - - - /** - * VARA - * - * Estimates variance based on a sample, including numbers, text, and logical values - * - * Excel Function: - * VARA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function VARA() { - // Return value - $returnValue = self::$_errorCodes['divisionbyzero']; - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = self::flattenArrayIndexed(func_get_args()); - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_string($arg)) && - (self::isValue($k))) { - return self::$_errorCodes['value']; - } elseif ((is_string($arg)) && - (!self::isMatrixValue($k))) { - } else { - // 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 *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); - } - return $returnValue; - } // function VARA() - - - /** - * VARP - * - * Calculates variance based on the entire population - * - * Excel Function: - * VARP(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @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) { - if (is_bool($arg)) { $arg = (integer) $arg; } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summerA += ($arg * $arg); - $summerB += $arg; - ++$aCount; - } - } - - // Return - if ($aCount > 0) { - $summerA *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * $aCount); - } - return $returnValue; - } // function VARP() - - - /** - * VARPA - * - * Calculates variance based on the entire population, including numbers, text, and logical values - * - * Excel Function: - * VARPA(value1[,value2[, ...]]) - * - * @access public - * @category Statistical Functions - * @param mixed $arg,... Data values - * @return float - */ - public static function VARPA() { - // Return value - $returnValue = self::$_errorCodes['divisionbyzero']; - - $summerA = $summerB = 0; - - // Loop through arguments - $aArgs = self::flattenArrayIndexed(func_get_args()); - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_string($arg)) && - (self::isValue($k))) { - return self::$_errorCodes['value']; - } elseif ((is_string($arg)) && - (!self::isMatrixValue($k))) { - } else { - // 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 *= $aCount; - $summerB *= $summerB; - $returnValue = ($summerA - $summerB) / ($aCount * $aCount); - } - return $returnValue; - } // function VARPA() - - - /** - * 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 = (is_null($order)) ? 0 : (integer) 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 = (is_null($significance)) ? 3 : (integer) 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 _checkTrendArrays(&$array1,&$array2) { - if (!is_array($array1)) { $array1 = array($array1); } - if (!is_array($array2)) { $array2 = array($array2); } - - $array1 = self::flattenArray($array1); - $array2 = self::flattenArray($array2); - foreach($array1 as $key => $value) { - if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { - unset($array1[$key]); - unset($array2[$key]); - } - } - foreach($array2 as $key => $value) { - if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { - unset($array1[$key]); - unset($array2[$key]); - } - } - $array1 = array_merge($array1); - $array2 = array_merge($array2); - - return True; - } // function _checkTrendArrays() - - - /** - * 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) { - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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) { - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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) { - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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) { - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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) { - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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=null) { - if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) { - return self::$_errorCodes['value']; - } - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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=null,$const=True,$stats=False) { - $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); - $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); - if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $xValueCount = count($xValues); - - - if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { - return self::$_errorCodes['na']; - } elseif ($yValueCount == 1) { - return 0; - } - - $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=null,$const=True,$stats=False) { - $const = (is_null($const)) ? True : (boolean) self::flattenSingleValue($const); - $stats = (is_null($stats)) ? False : (boolean) self::flattenSingleValue($stats); - if (is_null($xValues)) $xValues = range(1,count(self::flattenArray($yValues))); - - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $xValueCount = count($xValues); - - foreach($yValues as $value) { - if ($value <= 0.0) { - return self::$_errorCodes['num']; - } - } - - - if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { - return self::$_errorCodes['na']; - } elseif ($yValueCount == 1) { - return 1; - } - - $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); - if (!is_numeric($xValue)) { - return self::$_errorCodes['value']; - } - - if (!self::_checkTrendArrays($yValues,$xValues)) { - return self::$_errorCodes['value']; - } - $yValueCount = count($yValues); - $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 = (is_null($const)) ? True : (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 = (is_null($const)) ? True : (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; - } // function _romanCut() - - - public static function ROMAN($aValue, $style=0) { - $aValue = (integer) self::flattenSingleValue($aValue); - $style = (is_null($style)) ? 0 : (integer) self::flattenSingleValue($style); - if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) { - return self::$_errorCodes['value']; - } - if ($aValue == 0) { - return ''; - } - - $mill = Array('', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM'); - $cent = Array('', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'); - $tens = Array('', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'); - $ones = Array('', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'); - - $roman = ''; - while ($aValue > 5999) { - $roman .= 'M'; - $aValue -= 1000; - } - $m = self::_romanCut($aValue, 1000); $aValue %= 1000; - $c = self::_romanCut($aValue, 100); $aValue %= 100; - $t = self::_romanCut($aValue, 10); $aValue %= 10; - - return $roman.$mill[$m].$cent[$c].$tens[$t].$ones[$aValue]; - } // function ROMAN() - - - /** - * SUBTOTAL - * - * Returns a subtotal in a list or database. - * - * @param int the number 1 to 11 that specifies which function to - * use in calculating subtotals within a list. - * @param array of mixed Data Series - * @return float - */ - public static function SUBTOTAL() { - $aArgs = self::flattenArray(func_get_args()); - - // Calculate - $subtotal = array_shift($aArgs); - - if ((is_numeric($subtotal)) && (!is_string($subtotal))) { - switch($subtotal) { - case 1 : - return self::AVERAGE($aArgs); - break; - case 2 : - return self::COUNT($aArgs); - break; - case 3 : - return self::COUNTA($aArgs); - break; - case 4 : - return self::MAX($aArgs); - break; - case 5 : - return self::MIN($aArgs); - break; - case 6 : - return self::PRODUCT($aArgs); - break; - case 7 : - return self::STDEV($aArgs); - break; - case 8 : - return self::STDEVP($aArgs); - break; - case 9 : - return self::SUM($aArgs); - break; - case 10 : - return self::VARFunc($aArgs); - break; - case 11 : - return self::VARP($aArgs); - break; - } - } - return self::$_errorCodes['value']; - } // function SUBTOTAL() - - - /** - * SQRTPI - * - * Returns the square root of (number * pi). - * - * @param float $number Number - * @return float Square Root of Number * Pi - */ - public static function SQRTPI($number) { - $number = self::flattenSingleValue($number); - - if (is_numeric($number)) { - if ($number < 0) { - return self::$_errorCodes['num']; - } - return sqrt($number * M_PI) ; - } - return self::$_errorCodes['value']; - } // function SQRTPI() - - - /** - * FACT - * - * Returns the factorial of a number. - * - * @param float $factVal Factorial Value - * @return int Factorial - */ - public static function FACT($factVal) { - $factVal = self::flattenSingleValue($factVal); - - if (is_numeric($factVal)) { - if ($factVal < 0) { - return self::$_errorCodes['num']; - } - $factLoop = floor($factVal); - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - if ($factVal > $factLoop) { - return self::$_errorCodes['num']; - } - } - - $factorial = 1; - while ($factLoop > 1) { - $factorial *= $factLoop--; - } - return $factorial ; - } - return self::$_errorCodes['value']; - } // function FACT() - - - /** - * FACTDOUBLE - * - * Returns the double factorial of a number. - * - * @param float $factVal Factorial Value - * @return int Double Factorial - */ - public static function FACTDOUBLE($factVal) { - $factLoop = floor(self::flattenSingleValue($factVal)); - - if (is_numeric($factLoop)) { - if ($factVal < 0) { - return self::$_errorCodes['num']; - } - $factorial = 1; - while ($factLoop > 1) { - $factorial *= $factLoop--; - --$factLoop; - } - return $factorial ; - } - return self::$_errorCodes['value']; - } // function FACTDOUBLE() - - - /** - * MULTINOMIAL - * - * Returns the ratio of the factorial of a sum of values to the product of factorials. - * - * @param array of mixed Data Series - * @return float - */ - public static function MULTINOMIAL() { - // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - $summer = 0; - $divisor = 1; - foreach ($aArgs as $arg) { - // Is it a numeric value? - if (is_numeric($arg)) { - if ($arg < 1) { - return self::$_errorCodes['num']; - } - $summer += floor($arg); - $divisor *= self::FACT($arg); - } else { - return self::$_errorCodes['value']; - } - } - - // Return - if ($summer > 0) { - $summer = self::FACT($summer); - return $summer / $divisor; - } - return 0; - } // function MULTINOMIAL() - - - /** - * CEILING - * - * Returns number rounded up, away from zero, to the nearest multiple of significance. - * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number - */ - public static function CEILING($number,$significance=null) { - $number = self::flattenSingleValue($number); - $significance = self::flattenSingleValue($significance); - - if ((is_null($significance)) && (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC)) { - $significance = $number/abs($number); - } - - if ((is_numeric($number)) && (is_numeric($significance))) { - if (self::SIGN($number) == self::SIGN($significance)) { - if ($significance == 0.0) { - return 0; - } - return ceil($number / $significance) * $significance; - } else { - return self::$_errorCodes['num']; - } - } - return self::$_errorCodes['value']; - } // function CEILING() - - - /** - * EVEN - * - * Returns number rounded up to the nearest even integer. - * - * @param float $number Number to round - * @return int Rounded Number - */ - public static function EVEN($number) { - $number = self::flattenSingleValue($number); - - if (is_numeric($number)) { - $significance = 2 * self::SIGN($number); - return self::CEILING($number,$significance); - } - return self::$_errorCodes['value']; - } // function EVEN() - - - /** - * ODD - * - * Returns number rounded up to the nearest odd integer. - * - * @param float $number Number to round - * @return int Rounded Number - */ - public static function ODD($number) { - $number = self::flattenSingleValue($number); - - if (is_numeric($number)) { - $significance = self::SIGN($number); - if ($significance == 0) { - return 1; - } - $result = self::CEILING($number,$significance); - if (self::IS_EVEN($result)) { - $result += $significance; - } - return $result; - } - return self::$_errorCodes['value']; - } // function ODD() - - - /** - * INTVALUE - * - * Casts a floating point value to an integer - * - * @param float $number Number to cast to an integer - * @return integer Integer value - */ - public static function INTVALUE($number) { - $number = self::flattenSingleValue($number); - - if (is_numeric($number)) { - return (int) floor($number); - } - return self::$_errorCodes['value']; - } // function INTVALUE() - - - /** - * ROUNDUP - * - * Rounds a number up to a specified number of decimal places - * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number - */ - public static function ROUNDUP($number,$digits) { - $number = self::flattenSingleValue($number); - $digits = self::flattenSingleValue($digits); - - if ((is_numeric($number)) && (is_numeric($digits))) { - $significance = pow(10,$digits); - if ($number < 0.0) { - return floor($number * $significance) / $significance; - } else { - return ceil($number * $significance) / $significance; - } - } - return self::$_errorCodes['value']; - } // function ROUNDUP() - - - /** - * ROUNDDOWN - * - * Rounds a number down to a specified number of decimal places - * - * @param float $number Number to round - * @param int $digits Number of digits to which you want to round $number - * @return float Rounded Number - */ - public static function ROUNDDOWN($number,$digits) { - $number = self::flattenSingleValue($number); - $digits = self::flattenSingleValue($digits); - - if ((is_numeric($number)) && (is_numeric($digits))) { - $significance = pow(10,$digits); - if ($number < 0.0) { - return ceil($number * $significance) / $significance; - } else { - return floor($number * $significance) / $significance; - } - } - return self::$_errorCodes['value']; - } // function ROUNDDOWN() - - - /** - * MROUND - * - * Rounds a number to the nearest multiple of a specified value - * - * @param float $number Number to round - * @param int $multiple Multiple to which you want to round $number - * @return float Rounded Number - */ - public static function MROUND($number,$multiple) { - $number = self::flattenSingleValue($number); - $multiple = self::flattenSingleValue($multiple); - - if ((is_numeric($number)) && (is_numeric($multiple))) { - if ($multiple == 0) { - return 0; - } - if ((self::SIGN($number)) == (self::SIGN($multiple))) { - $multiplier = 1 / $multiple; - return round($number * $multiplier) / $multiplier; - } - return self::$_errorCodes['num']; - } - return self::$_errorCodes['value']; - } // function MROUND() - - - /** - * SIGN - * - * Determines the sign of a number. Returns 1 if the number is positive, zero (0) - * if the number is 0, and -1 if the number is negative. - * - * @param float $number Number to round - * @return int sign value - */ - public static function SIGN($number) { - $number = self::flattenSingleValue($number); - - if (is_numeric($number)) { - if ($number == 0.0) { - return 0; - } - return $number / abs($number); - } - return self::$_errorCodes['value']; - } // function SIGN() - - - /** - * FLOOR - * - * Rounds number down, toward zero, to the nearest multiple of significance. - * - * @param float $number Number to round - * @param float $significance Significance - * @return float Rounded Number - */ - public static function FLOOR($number,$significance=null) { - $number = self::flattenSingleValue($number); - $significance = self::flattenSingleValue($significance); - - if ((is_null($significance)) && (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC)) { - $significance = $number/abs($number); - } - - if ((is_numeric($number)) && (is_numeric($significance))) { - if ((float) $significance == 0.0) { - return self::$_errorCodes['divisionbyzero']; - } - if (self::SIGN($number) == self::SIGN($significance)) { - return floor($number / $significance) * $significance; - } else { - return self::$_errorCodes['num']; - } - } - return self::$_errorCodes['value']; - } // function FLOOR() - - - /** - * PERMUT - * - * Returns the number of permutations for a given number of objects that can be - * selected from number objects. A permutation is any set or subset of objects or - * events where internal order is significant. Permutations are different from - * combinations, for which the internal order is not significant. Use this function - * for lottery-style probability calculations. - * - * @param int $numObjs Number of different objects - * @param int $numInSet Number of objects in each permutation - * @return int Number of permutations - */ - public static function PERMUT($numObjs,$numInSet) { - $numObjs = self::flattenSingleValue($numObjs); - $numInSet = self::flattenSingleValue($numInSet); - - if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { - $numInSet = floor($numInSet); - if ($numObjs < $numInSet) { - return self::$_errorCodes['num']; - } - return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)); - } - return self::$_errorCodes['value']; - } // function PERMUT() - - - /** - * COMBIN - * - * Returns the number of combinations for a given number of items. Use COMBIN to - * determine the total possible number of groups for a given number of items. - * - * @param int $numObjs Number of different objects - * @param int $numInSet Number of objects in each combination - * @return int Number of combinations - */ - public static function COMBIN($numObjs,$numInSet) { - $numObjs = self::flattenSingleValue($numObjs); - $numInSet = self::flattenSingleValue($numInSet); - - if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { - if ($numObjs < $numInSet) { - return self::$_errorCodes['num']; - } elseif ($numInSet < 0) { - return self::$_errorCodes['num']; - } - return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet); - } - return self::$_errorCodes['value']; - } // function COMBIN() - - - /** - * SERIESSUM - * - * Returns the sum of a power series - * - * @param float $x Input value to the power series - * @param float $n Initial power to which you want to raise $x - * @param float $m Step by which to increase $n for each term in the series - * @param array of mixed Data Series - * @return float - */ - public static function SERIESSUM() { - // Return value - $returnValue = 0; - - // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - - $x = array_shift($aArgs); - $n = array_shift($aArgs); - $m = array_shift($aArgs); - - if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) { - // Calculate - $i = 0; - foreach($aArgs as $arg) { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $returnValue += $arg * pow($x,$n + ($m * $i++)); - } else { - return self::$_errorCodes['value']; - } - } - // Return - return $returnValue; - } - return self::$_errorCodes['value']; - } // function SERIESSUM() - - - /** - * STANDARDIZE - * - * Returns a normalized value from a distribution characterized by mean and standard_dev. - * - * @param float $value Value to normalize - * @param float $mean Mean Value - * @param float $stdDev Standard Deviation - * @return float Standardized value - */ - public static function STANDARDIZE($value,$mean,$stdDev) { - $value = self::flattenSingleValue($value); - $mean = self::flattenSingleValue($mean); - $stdDev = self::flattenSingleValue($stdDev); - - if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { - if ($stdDev <= 0) { - return self::$_errorCodes['num']; - } - return ($value - $mean) / $stdDev ; - } - return self::$_errorCodes['value']; - } // function STANDARDIZE() - - - // - // Private method to return an array of the factors of the input value - // - private static function _factors($value) { - $startVal = floor(sqrt($value)); - - $factorArray = array(); - for ($i = $startVal; $i > 1; --$i) { - if (($value % $i) == 0) { - $factorArray = array_merge($factorArray,self::_factors($value / $i)); - $factorArray = array_merge($factorArray,self::_factors($i)); - if ($i <= sqrt($value)) { - break; - } - } - } - if (count($factorArray) > 0) { - rsort($factorArray); - return $factorArray; - } else { - return array((integer) $value); - } - } // function _factors() - - - /** - * LCM - * - * Returns the lowest common multiplier of a series of numbers - * - * @param $array Values to calculate the Lowest Common Multiplier - * @return int Lowest Common Multiplier - */ - public static function LCM() { - $aArgs = self::flattenArray(func_get_args()); - - $returnValue = 1; - $allPoweredFactors = array(); - foreach($aArgs as $value) { - if (!is_numeric($value)) { - return self::$_errorCodes['value']; - } - if ($value == 0) { - return 0; - } elseif ($value < 0) { - return self::$_errorCodes['num']; - } - $myFactors = self::_factors(floor($value)); - $myCountedFactors = array_count_values($myFactors); - $myPoweredFactors = array(); - foreach($myCountedFactors as $myCountedFactor => $myCountedPower) { - $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor,$myCountedPower); - } - foreach($myPoweredFactors as $myPoweredValue => $myPoweredFactor) { - if (array_key_exists($myPoweredValue,$allPoweredFactors)) { - if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) { - $allPoweredFactors[$myPoweredValue] = $myPoweredFactor; - } - } else { - $allPoweredFactors[$myPoweredValue] = $myPoweredFactor; - } - } - } - foreach($allPoweredFactors as $allPoweredFactor) { - $returnValue *= (integer) $allPoweredFactor; - } - return $returnValue; - } // function LCM() - - - /** - * GCD - * - * Returns the greatest common divisor of a series of numbers - * - * @param $array Values to calculate the Greatest Common Divisor - * @return int Greatest Common Divisor - */ - public static function GCD() { - $aArgs = self::flattenArray(func_get_args()); - - $returnValue = 1; - $allPoweredFactors = array(); - foreach($aArgs as $value) { - if ($value == 0) { - break; - } - $myFactors = self::_factors($value); - $myCountedFactors = array_count_values($myFactors); - $allValuesFactors[] = $myCountedFactors; - } - $allValuesCount = count($allValuesFactors); - $mergedArray = $allValuesFactors[0]; - for ($i=1;$i < $allValuesCount; ++$i) { - $mergedArray = array_intersect_key($mergedArray,$allValuesFactors[$i]); - } - $mergedArrayValues = count($mergedArray); - if ($mergedArrayValues == 0) { - return $returnValue; - } elseif ($mergedArrayValues > 1) { - foreach($mergedArray as $mergedKey => $mergedValue) { - foreach($allValuesFactors as $highestPowerTest) { - foreach($highestPowerTest as $testKey => $testValue) { - if (($testKey == $mergedKey) && ($testValue < $mergedValue)) { - $mergedArray[$mergedKey] = $testValue; - $mergedValue = $testValue; - } - } - } - } - - $returnValue = 1; - foreach($mergedArray as $key => $value) { - $returnValue *= pow($key,$value); - } - return $returnValue; - } else { - $keys = array_keys($mergedArray); - $key = $keys[0]; - $value = $mergedArray[$key]; - foreach($allValuesFactors as $testValue) { - foreach($testValue as $mergedKey => $mergedValue) { - if (($mergedKey == $key) && ($mergedValue < $value)) { - $value = $mergedValue; - } - } - } - return pow($key,$value); - } - } // function GCD() - - - /** - * BINOMDIST - * - * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with - * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, - * when trials are independent, and when the probability of success is constant throughout the - * experiment. For example, BINOMDIST can calculate the probability that two of the next three - * babies born are male. - * - * @param float $value Number of successes in trials - * @param float $trials Number of trials - * @param float $probability Probability of success on each trial - * @param boolean $cumulative - * @return float - * - * @todo Cumulative distribution function - * - */ - public static function BINOMDIST($value, $trials, $probability, $cumulative) { - $value = floor(self::flattenSingleValue($value)); - $trials = floor(self::flattenSingleValue($trials)); - $probability = self::flattenSingleValue($probability); - - if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) { - if (($value < 0) || ($value > $trials)) { - return self::$_errorCodes['num']; - } - if (($probability < 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - $summer = 0; - for ($i = 0; $i <= $value; ++$i) { - $summer += self::COMBIN($trials,$i) * pow($probability,$i) * pow(1 - $probability,$trials - $i); - } - return $summer; - } else { - return self::COMBIN($trials,$value) * pow($probability,$value) * pow(1 - $probability,$trials - $value) ; - } - } - } - return self::$_errorCodes['value']; - } // function BINOMDIST() - - - /** - * NEGBINOMDIST - * - * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that - * there will be number_f failures before the number_s-th success, when the constant - * probability of a success is probability_s. This function is similar to the binomial - * distribution, except that the number of successes is fixed, and the number of trials is - * variable. Like the binomial, trials are assumed to be independent. - * - * @param float $failures Number of Failures - * @param float $successes Threshold number of Successes - * @param float $probability Probability of success on each trial - * @return float - * - */ - public static function NEGBINOMDIST($failures, $successes, $probability) { - $failures = floor(self::flattenSingleValue($failures)); - $successes = floor(self::flattenSingleValue($successes)); - $probability = self::flattenSingleValue($probability); - - if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) { - if (($failures < 0) || ($successes < 1)) { - return self::$_errorCodes['num']; - } - if (($probability < 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - if (($failures + $successes - 1) <= 0) { - return self::$_errorCodes['num']; - } - } - return (self::COMBIN($failures + $successes - 1,$successes - 1)) * (pow($probability,$successes)) * (pow(1 - $probability,$failures)) ; - } - return self::$_errorCodes['value']; - } // function NEGBINOMDIST() - - - /** - * CRITBINOM - * - * Returns the smallest value for which the cumulative binomial distribution is greater - * than or equal to a criterion value - * - * See http://support.microsoft.com/kb/828117/ for details of the algorithm used - * - * @param float $trials number of Bernoulli trials - * @param float $probability probability of a success on each trial - * @param float $alpha criterion value - * @return int - * - * @todo Warning. This implementation differs from the algorithm detailed on the MS - * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess - * This eliminates a potential endless loop error, but may have an adverse affect on the - * accuracy of the function (although all my tests have so far returned correct results). - * - */ - public static function CRITBINOM($trials, $probability, $alpha) { - $trials = floor(self::flattenSingleValue($trials)); - $probability = self::flattenSingleValue($probability); - $alpha = self::flattenSingleValue($alpha); - - if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) { - if ($trials < 0) { - return self::$_errorCodes['num']; - } - if (($probability < 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - if (($alpha < 0) || ($alpha > 1)) { - return self::$_errorCodes['num']; - } - if ($alpha <= 0.5) { - $t = sqrt(log(1 / ($alpha * $alpha))); - $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)); - } else { - $t = sqrt(log(1 / pow(1 - $alpha,2))); - $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t); - } - $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability))); - if ($Guess < 0) { - $Guess = 0; - } elseif ($Guess > $trials) { - $Guess = $trials; - } - - $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0; - $EssentiallyZero = 10e-12; - - $m = floor($trials * $probability); - ++$TotalUnscaledProbability; - if ($m == $Guess) { ++$UnscaledPGuess; } - if ($m <= $Guess) { ++$UnscaledCumPGuess; } - - $PreviousValue = 1; - $Done = False; - $k = $m + 1; - while ((!$Done) && ($k <= $trials)) { - $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability)); - $TotalUnscaledProbability += $CurrentValue; - if ($k == $Guess) { $UnscaledPGuess += $CurrentValue; } - if ($k <= $Guess) { $UnscaledCumPGuess += $CurrentValue; } - if ($CurrentValue <= $EssentiallyZero) { $Done = True; } - $PreviousValue = $CurrentValue; - ++$k; - } - - $PreviousValue = 1; - $Done = False; - $k = $m - 1; - while ((!$Done) && ($k >= 0)) { - $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability); - $TotalUnscaledProbability += $CurrentValue; - if ($k == $Guess) { $UnscaledPGuess += $CurrentValue; } - if ($k <= $Guess) { $UnscaledCumPGuess += $CurrentValue; } - if ($CurrentValue <= $EssentiallyZero) { $Done = True; } - $PreviousValue = $CurrentValue; - --$k; - } - - $PGuess = $UnscaledPGuess / $TotalUnscaledProbability; - $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability; - -// $CumPGuessMinus1 = $CumPGuess - $PGuess; - $CumPGuessMinus1 = $CumPGuess - 1; - - while (True) { - if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) { - return $Guess; - } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) { - $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability); - $CumPGuessMinus1 = $CumPGuess; - $CumPGuess = $CumPGuess + $PGuessPlus1; - $PGuess = $PGuessPlus1; - ++$Guess; - } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) { - $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability; - $CumPGuess = $CumPGuessMinus1; - $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess; - $PGuess = $PGuessMinus1; - --$Guess; - } - } - } - return self::$_errorCodes['value']; - } // function CRITBINOM() - - - /** - * CHIDIST - * - * Returns the one-tailed probability of the chi-squared distribution. - * - * @param float $value Value for the function - * @param float $degrees degrees of freedom - * @return float - */ - public static function CHIDIST($value, $degrees) { - $value = self::flattenSingleValue($value); - $degrees = floor(self::flattenSingleValue($degrees)); - - if ((is_numeric($value)) && (is_numeric($degrees))) { - if ($degrees < 1) { - return self::$_errorCodes['num']; - } - if ($value < 0) { - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - return 1; - } - return self::$_errorCodes['num']; - } - return 1 - (self::_incompleteGamma($degrees/2,$value/2) / self::_gamma($degrees/2)); - } - return self::$_errorCodes['value']; - } // function CHIDIST() - - - /** - * CHIINV - * - * Returns the one-tailed probability of the chi-squared distribution. - * - * @param float $probability Probability for the function - * @param float $degrees degrees of freedom - * @return float - */ - public static function CHIINV($probability, $degrees) { - $probability = self::flattenSingleValue($probability); - $degrees = floor(self::flattenSingleValue($degrees)); - - if ((is_numeric($probability)) && (is_numeric($degrees))) { - - $xLo = 100; - $xHi = 0; - - $x = $xNew = 1; - $dx = 1; - $i = 0; - - while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { - // Apply Newton-Raphson step - $result = self::CHIDIST($x, $degrees); - $error = $result - $probability; - if ($error == 0.0) { - $dx = 0; - } elseif ($error < 0.0) { - $xLo = $x; - } else { - $xHi = $x; - } - // Avoid division by zero - if ($result != 0.0) { - $dx = $error / $result; - $xNew = $x - $dx; - } - // If the NR fails to converge (which for example may be the - // case if the initial guess is too rough) we apply a bisection - // step to determine a more narrow interval around the root. - if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { - $xNew = ($xLo + $xHi) / 2; - $dx = $xNew - $x; - } - $x = $xNew; - } - if ($i == MAX_ITERATIONS) { - return self::$_errorCodes['na']; - } - return round($x,12); - } - return self::$_errorCodes['value']; - } // function CHIINV() - - - /** - * EXPONDIST - * - * Returns the exponential distribution. Use EXPONDIST to model the time between events, - * such as how long an automated bank teller takes to deliver cash. For example, you can - * use EXPONDIST to determine the probability that the process takes at most 1 minute. - * - * @param float $value Value of the function - * @param float $lambda The parameter value - * @param boolean $cumulative - * @return float - */ - public static function EXPONDIST($value, $lambda, $cumulative) { - $value = self::flattenSingleValue($value); - $lambda = self::flattenSingleValue($lambda); - $cumulative = self::flattenSingleValue($cumulative); - - if ((is_numeric($value)) && (is_numeric($lambda))) { - if (($value < 0) || ($lambda < 0)) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - return 1 - exp(0-$value*$lambda); - } else { - return $lambda * exp(0-$value*$lambda); - } - } - } - return self::$_errorCodes['value']; - } // function EXPONDIST() - - - /** - * FISHER - * - * Returns the Fisher transformation at x. This transformation produces a function that - * is normally distributed rather than skewed. Use this function to perform hypothesis - * testing on the correlation coefficient. - * - * @param float $value - * @return float - */ - public static function FISHER($value) { - $value = self::flattenSingleValue($value); - - if (is_numeric($value)) { - if (($value <= -1) || ($value >= 1)) { - return self::$_errorCodes['num']; - } - return 0.5 * log((1+$value)/(1-$value)); - } - return self::$_errorCodes['value']; - } // function FISHER() - - - /** - * FISHERINV - * - * Returns the inverse of the Fisher transformation. Use this transformation when - * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then - * FISHERINV(y) = x. - * - * @param float $value - * @return float - */ - public static function FISHERINV($value) { - $value = self::flattenSingleValue($value); - - if (is_numeric($value)) { - return (exp(2 * $value) - 1) / (exp(2 * $value) + 1); - } - return self::$_errorCodes['value']; - } // function FISHERINV() - - - // Function cache for _logBeta function - private static $_logBetaCache_p = 0.0; - private static $_logBetaCache_q = 0.0; - private static $_logBetaCache_result = 0.0; - - /** - * The natural logarithm of the beta function. - * @param p require p>0 - * @param q require q>0 - * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow - * @author Jaco van Kooten - */ - private static function _logBeta($p, $q) { - if ($p != self::$_logBetaCache_p || $q != self::$_logBetaCache_q) { - self::$_logBetaCache_p = $p; - self::$_logBetaCache_q = $q; - if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) { - self::$_logBetaCache_result = 0.0; - } else { - self::$_logBetaCache_result = self::_logGamma($p) + self::_logGamma($q) - self::_logGamma($p + $q); - } - } - return self::$_logBetaCache_result; - } // function _logBeta() - - - /** - * Evaluates of continued fraction part of incomplete beta function. - * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). - * @author Jaco van Kooten - */ - private static function _betaFraction($x, $p, $q) { - $c = 1.0; - $sum_pq = $p + $q; - $p_plus = $p + 1.0; - $p_minus = $p - 1.0; - $h = 1.0 - $sum_pq * $x / $p_plus; - if (abs($h) < XMININ) { - $h = XMININ; - } - $h = 1.0 / $h; - $frac = $h; - $m = 1; - $delta = 0.0; - while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION ) { - $m2 = 2 * $m; - // even index for d - $d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2)); - $h = 1.0 + $d * $h; - if (abs($h) < XMININ) { - $h = XMININ; - } - $h = 1.0 / $h; - $c = 1.0 + $d / $c; - if (abs($c) < XMININ) { - $c = XMININ; - } - $frac *= $h * $c; - // odd index for d - $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2)); - $h = 1.0 + $d * $h; - if (abs($h) < XMININ) { - $h = XMININ; - } - $h = 1.0 / $h; - $c = 1.0 + $d / $c; - if (abs($c) < XMININ) { - $c = XMININ; - } - $delta = $h * $c; - $frac *= $delta; - ++$m; - } - return $frac; - } // function _betaFraction() - - - /** - * logGamma function - * - * @version 1.1 - * @author Jaco van Kooten - * - * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher. - * - * The natural logarithm of the gamma function.
- * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz
- * Applied Mathematics Division
- * Argonne National Laboratory
- * Argonne, IL 60439
- *

- * References: - *

    - *
  1. W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural - * Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.
  2. - *
  3. K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.
  4. - *
  5. Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.
  6. - *
- *

- *

- * From the original documentation: - *

- *

- * This routine calculates the LOG(GAMMA) function for a positive real argument X. - * Computation is based on an algorithm outlined in references 1 and 2. - * The program uses rational functions that theoretically approximate LOG(GAMMA) - * to at least 18 significant decimal digits. The approximation for X > 12 is from - * reference 3, while approximations for X < 12.0 are similar to those in reference - * 1, but are unpublished. The accuracy achieved depends on the arithmetic system, - * the compiler, the intrinsic functions, and proper selection of the - * machine-dependent constants. - *

- *

- * Error returns:
- * The program returns the value XINF for X .LE. 0.0 or when overflow would occur. - * The computation is believed to be free of underflow and overflow. - *

- * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305 - */ - - // Function cache for logGamma - private static $_logGammaCache_result = 0.0; - private static $_logGammaCache_x = 0.0; - - private static function _logGamma($x) { - // Log Gamma related constants - static $lg_d1 = -0.5772156649015328605195174; - static $lg_d2 = 0.4227843350984671393993777; - static $lg_d4 = 1.791759469228055000094023; - - static $lg_p1 = array( 4.945235359296727046734888, - 201.8112620856775083915565, - 2290.838373831346393026739, - 11319.67205903380828685045, - 28557.24635671635335736389, - 38484.96228443793359990269, - 26377.48787624195437963534, - 7225.813979700288197698961 ); - static $lg_p2 = array( 4.974607845568932035012064, - 542.4138599891070494101986, - 15506.93864978364947665077, - 184793.2904445632425417223, - 1088204.76946882876749847, - 3338152.967987029735917223, - 5106661.678927352456275255, - 3074109.054850539556250927 ); - static $lg_p4 = array( 14745.02166059939948905062, - 2426813.369486704502836312, - 121475557.4045093227939592, - 2663432449.630976949898078, - 29403789566.34553899906876, - 170266573776.5398868392998, - 492612579337.743088758812, - 560625185622.3951465078242 ); - - static $lg_q1 = array( 67.48212550303777196073036, - 1113.332393857199323513008, - 7738.757056935398733233834, - 27639.87074403340708898585, - 54993.10206226157329794414, - 61611.22180066002127833352, - 36351.27591501940507276287, - 8785.536302431013170870835 ); - static $lg_q2 = array( 183.0328399370592604055942, - 7765.049321445005871323047, - 133190.3827966074194402448, - 1136705.821321969608938755, - 5267964.117437946917577538, - 13467014.54311101692290052, - 17827365.30353274213975932, - 9533095.591844353613395747 ); - static $lg_q4 = array( 2690.530175870899333379843, - 639388.5654300092398984238, - 41355999.30241388052042842, - 1120872109.61614794137657, - 14886137286.78813811542398, - 101680358627.2438228077304, - 341747634550.7377132798597, - 446315818741.9713286462081 ); - - static $lg_c = array( -0.001910444077728, - 8.4171387781295e-4, - -5.952379913043012e-4, - 7.93650793500350248e-4, - -0.002777777777777681622553, - 0.08333333333333333331554247, - 0.0057083835261 ); - - // Rough estimate of the fourth root of logGamma_xBig - static $lg_frtbig = 2.25e76; - static $pnt68 = 0.6796875; - - - if ($x == self::$_logGammaCache_x) { - return self::$_logGammaCache_result; - } - $y = $x; - if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) { - if ($y <= EPS) { - $res = -log(y); - } elseif ($y <= 1.5) { - // --------------------- - // EPS .LT. X .LE. 1.5 - // --------------------- - if ($y < $pnt68) { - $corr = -log($y); - $xm1 = $y; - } else { - $corr = 0.0; - $xm1 = $y - 1.0; - } - if ($y <= 0.5 || $y >= $pnt68) { - $xden = 1.0; - $xnum = 0.0; - for ($i = 0; $i < 8; ++$i) { - $xnum = $xnum * $xm1 + $lg_p1[$i]; - $xden = $xden * $xm1 + $lg_q1[$i]; - } - $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden)); - } else { - $xm2 = $y - 1.0; - $xden = 1.0; - $xnum = 0.0; - for ($i = 0; $i < 8; ++$i) { - $xnum = $xnum * $xm2 + $lg_p2[$i]; - $xden = $xden * $xm2 + $lg_q2[$i]; - } - $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); - } - } elseif ($y <= 4.0) { - // --------------------- - // 1.5 .LT. X .LE. 4.0 - // --------------------- - $xm2 = $y - 2.0; - $xden = 1.0; - $xnum = 0.0; - for ($i = 0; $i < 8; ++$i) { - $xnum = $xnum * $xm2 + $lg_p2[$i]; - $xden = $xden * $xm2 + $lg_q2[$i]; - } - $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); - } elseif ($y <= 12.0) { - // ---------------------- - // 4.0 .LT. X .LE. 12.0 - // ---------------------- - $xm4 = $y - 4.0; - $xden = -1.0; - $xnum = 0.0; - for ($i = 0; $i < 8; ++$i) { - $xnum = $xnum * $xm4 + $lg_p4[$i]; - $xden = $xden * $xm4 + $lg_q4[$i]; - } - $res = $lg_d4 + $xm4 * ($xnum / $xden); - } else { - // --------------------------------- - // Evaluate for argument .GE. 12.0 - // --------------------------------- - $res = 0.0; - if ($y <= $lg_frtbig) { - $res = $lg_c[6]; - $ysq = $y * $y; - for ($i = 0; $i < 6; ++$i) - $res = $res / $ysq + $lg_c[$i]; - } - $res /= $y; - $corr = log($y); - $res = $res + log(SQRT2PI) - 0.5 * $corr; - $res += $y * ($corr - 1.0); - } - } else { - // -------------------------- - // Return for bad arguments - // -------------------------- - $res = MAX_VALUE; - } - // ------------------------------ - // Final adjustments and return - // ------------------------------ - self::$_logGammaCache_x = $x; - self::$_logGammaCache_result = $res; - return $res; - } // function _logGamma() - - - /** - * Beta function. - * - * @author Jaco van Kooten - * - * @param p require p>0 - * @param q require q>0 - * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow - */ - private static function _beta($p, $q) { - if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) { - return 0.0; - } else { - return exp(self::_logBeta($p, $q)); - } - } // function _beta() - - - /** - * Incomplete beta function - * - * @author Jaco van Kooten - * @author Paul Meagher - * - * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992). - * @param x require 0<=x<=1 - * @param p require p>0 - * @param q require q>0 - * @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 - */ - private static function _incompleteBeta($x, $p, $q) { - if ($x <= 0.0) { - return 0.0; - } elseif ($x >= 1.0) { - return 1.0; - } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) { - return 0.0; - } - $beta_gam = exp((0 - self::_logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x)); - if ($x < ($p + 1.0) / ($p + $q + 2.0)) { - return $beta_gam * self::_betaFraction($x, $p, $q) / $p; - } else { - return 1.0 - ($beta_gam * self::_betaFraction(1 - $x, $q, $p) / $q); - } - } // function _incompleteBeta() - - - /** - * BETADIST - * - * Returns the beta distribution. - * - * @param float $value Value at which you want to evaluate the distribution - * @param float $alpha Parameter to the distribution - * @param float $beta Parameter to the distribution - * @param boolean $cumulative - * @return float - * - */ - public static function BETADIST($value,$alpha,$beta,$rMin=0,$rMax=1) { - $value = self::flattenSingleValue($value); - $alpha = self::flattenSingleValue($alpha); - $beta = self::flattenSingleValue($beta); - $rMin = self::flattenSingleValue($rMin); - $rMax = self::flattenSingleValue($rMax); - - if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) { - if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) { - return self::$_errorCodes['num']; - } - if ($rMin > $rMax) { - $tmp = $rMin; - $rMin = $rMax; - $rMax = $tmp; - } - $value -= $rMin; - $value /= ($rMax - $rMin); - return self::_incompleteBeta($value,$alpha,$beta); - } - return self::$_errorCodes['value']; - } // function BETADIST() - - - /** - * BETAINV - * - * Returns the inverse of the beta distribution. - * - * @param float $probability Probability at which you want to evaluate the distribution - * @param float $alpha Parameter to the distribution - * @param float $beta Parameter to the distribution - * @param boolean $cumulative - * @return float - * - */ - public static function BETAINV($probability,$alpha,$beta,$rMin=0,$rMax=1) { - $probability = self::flattenSingleValue($probability); - $alpha = self::flattenSingleValue($alpha); - $beta = self::flattenSingleValue($beta); - $rMin = self::flattenSingleValue($rMin); - $rMax = self::flattenSingleValue($rMax); - - if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) { - if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - if ($rMin > $rMax) { - $tmp = $rMin; - $rMin = $rMax; - $rMax = $tmp; - } - $a = 0; - $b = 2; - - $i = 0; - while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) { - $guess = ($a + $b) / 2; - $result = self::BETADIST($guess, $alpha, $beta); - if (($result == $probability) || ($result == 0)) { - $b = $a; - } elseif ($result > $probability) { - $b = $guess; - } else { - $a = $guess; - } - } - if ($i == MAX_ITERATIONS) { - return self::$_errorCodes['na']; - } - return round($rMin + $guess * ($rMax - $rMin),12); - } - return self::$_errorCodes['value']; - } // function BETAINV() - - - // - // Private implementation of the incomplete Gamma function - // - private static function _incompleteGamma($a,$x) { - static $max = 32; - $summer = 0; - for ($n=0; $n<=$max; ++$n) { - $divisor = $a; - for ($i=1; $i<=$n; ++$i) { - $divisor *= ($a + $i); - } - $summer += (pow($x,$n) / $divisor); - } - return pow($x,$a) * exp(0-$x) * $summer; - } // function _incompleteGamma() - - - // - // Private implementation of the Gamma function - // - private static function _gamma($data) { - if ($data == 0.0) return 0; - - static $p0 = 1.000000000190015; - static $p = array ( 1 => 76.18009172947146, - 2 => -86.50532032941677, - 3 => 24.01409824083091, - 4 => -1.231739572450155, - 5 => 1.208650973866179e-3, - 6 => -5.395239384953e-6 - ); - - $y = $x = $data; - $tmp = $x + 5.5; - $tmp -= ($x + 0.5) * log($tmp); - - $summer = $p0; - for ($j=1;$j<=6;++$j) { - $summer += ($p[$j] / ++$y); - } - return exp(0 - $tmp + log(SQRT2PI * $summer / $x)); - } // function _gamma() - - - /** - * GAMMADIST - * - * Returns the gamma distribution. - * - * @param float $value Value at which you want to evaluate the distribution - * @param float $a Parameter to the distribution - * @param float $b Parameter to the distribution - * @param boolean $cumulative - * @return float - * - */ - public static function GAMMADIST($value,$a,$b,$cumulative) { - $value = self::flattenSingleValue($value); - $a = self::flattenSingleValue($a); - $b = self::flattenSingleValue($b); - - if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) { - if (($value < 0) || ($a <= 0) || ($b <= 0)) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - return self::_incompleteGamma($a,$value / $b) / self::_gamma($a); - } else { - return (1 / (pow($b,$a) * self::_gamma($a))) * pow($value,$a-1) * exp(0-($value / $b)); - } - } - } - return self::$_errorCodes['value']; - } // function GAMMADIST() - - - /** - * GAMMAINV - * - * Returns the inverse of the beta distribution. - * - * @param float $probability Probability at which you want to evaluate the distribution - * @param float $alpha Parameter to the distribution - * @param float $beta Parameter to the distribution - * @return float - * - */ - public static function GAMMAINV($probability,$alpha,$beta) { - $probability = self::flattenSingleValue($probability); - $alpha = self::flattenSingleValue($alpha); - $beta = self::flattenSingleValue($beta); - - if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) { - if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - - $xLo = 0; - $xHi = $alpha * $beta * 5; - - $x = $xNew = 1; - $error = $pdf = 0; - $dx = 1024; - $i = 0; - - while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { - // Apply Newton-Raphson step - $error = self::GAMMADIST($x, $alpha, $beta, True) - $probability; - if ($error < 0.0) { - $xLo = $x; - } else { - $xHi = $x; - } - $pdf = self::GAMMADIST($x, $alpha, $beta, False); - // Avoid division by zero - if ($pdf != 0.0) { - $dx = $error / $pdf; - $xNew = $x - $dx; - } - // If the NR fails to converge (which for example may be the - // case if the initial guess is too rough) we apply a bisection - // step to determine a more narrow interval around the root. - if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) { - $xNew = ($xLo + $xHi) / 2; - $dx = $xNew - $x; - } - $x = $xNew; - } - if ($i == MAX_ITERATIONS) { - return self::$_errorCodes['na']; - } - return $x; - } - return self::$_errorCodes['value']; - } // function GAMMAINV() - - - /** - * GAMMALN - * - * Returns the natural logarithm of the gamma function. - * - * @param float $value - * @return float - */ - public static function GAMMALN($value) { - $value = self::flattenSingleValue($value); - - if (is_numeric($value)) { - if ($value <= 0) { - return self::$_errorCodes['num']; - } - return log(self::_gamma($value)); - } - return self::$_errorCodes['value']; - } // function GAMMALN() - - - /** - * NORMDIST - * - * Returns the normal distribution for the specified mean and standard deviation. This - * function has a very wide range of applications in statistics, including hypothesis - * testing. - * - * @param float $value - * @param float $mean Mean Value - * @param float $stdDev Standard Deviation - * @param boolean $cumulative - * @return float - * - */ - public static function NORMDIST($value, $mean, $stdDev, $cumulative) { - $value = self::flattenSingleValue($value); - $mean = self::flattenSingleValue($mean); - $stdDev = self::flattenSingleValue($stdDev); - - if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { - if ($stdDev < 0) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - return 0.5 * (1 + self::_erfVal(($value - $mean) / ($stdDev * sqrt(2)))); - } else { - return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * ($stdDev * $stdDev)))); - } - } - } - return self::$_errorCodes['value']; - } // function NORMDIST() - - - /** - * NORMSDIST - * - * Returns the standard normal cumulative distribution function. The distribution has - * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a - * table of standard normal curve areas. - * - * @param float $value - * @return float - */ - public static function NORMSDIST($value) { - $value = self::flattenSingleValue($value); - - return self::NORMDIST($value, 0, 1, True); - } // function NORMSDIST() - - - /** - * LOGNORMDIST - * - * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed - * with parameters mean and standard_dev. - * - * @param float $value - * @return float - */ - public static function LOGNORMDIST($value, $mean, $stdDev) { - $value = self::flattenSingleValue($value); - $mean = self::flattenSingleValue($mean); - $stdDev = self::flattenSingleValue($stdDev); - - if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { - if (($value <= 0) || ($stdDev <= 0)) { - return self::$_errorCodes['num']; - } - return self::NORMSDIST((log($value) - $mean) / $stdDev); - } - return self::$_errorCodes['value']; - } // function LOGNORMDIST() - - - /*************************************************************************** - * inverse_ncdf.php - * ------------------- - * begin : Friday, January 16, 2004 - * copyright : (C) 2004 Michael Nickerson - * email : nickersonm@yahoo.com - * - ***************************************************************************/ - private static function _inverse_ncdf($p) { - // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to - // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as - // a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html - // I have not checked the accuracy of this implementation. Be aware that PHP - // will truncate the coeficcients to 14 digits. - - // You have permission to use and distribute this function freely for - // whatever purpose you want, but please show common courtesy and give credit - // where credit is due. - - // Input paramater is $p - probability - where 0 < p < 1. - - // Coefficients in rational approximations - static $a = array( 1 => -3.969683028665376e+01, - 2 => 2.209460984245205e+02, - 3 => -2.759285104469687e+02, - 4 => 1.383577518672690e+02, - 5 => -3.066479806614716e+01, - 6 => 2.506628277459239e+00 - ); - - static $b = array( 1 => -5.447609879822406e+01, - 2 => 1.615858368580409e+02, - 3 => -1.556989798598866e+02, - 4 => 6.680131188771972e+01, - 5 => -1.328068155288572e+01 - ); - - static $c = array( 1 => -7.784894002430293e-03, - 2 => -3.223964580411365e-01, - 3 => -2.400758277161838e+00, - 4 => -2.549732539343734e+00, - 5 => 4.374664141464968e+00, - 6 => 2.938163982698783e+00 - ); - - static $d = array( 1 => 7.784695709041462e-03, - 2 => 3.224671290700398e-01, - 3 => 2.445134137142996e+00, - 4 => 3.754408661907416e+00 - ); - - // Define lower and upper region break-points. - $p_low = 0.02425; //Use lower region approx. below this - $p_high = 1 - $p_low; //Use upper region approx. above this - - if (0 < $p && $p < $p_low) { - // Rational approximation for lower region. - $q = sqrt(-2 * log($p)); - return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / - (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); - } elseif ($p_low <= $p && $p <= $p_high) { - // Rational approximation for central region. - $q = $p - 0.5; - $r = $q * $q; - return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q / - ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1); - } elseif ($p_high < $p && $p < 1) { - // Rational approximation for upper region. - $q = sqrt(-2 * log(1 - $p)); - return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / - (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); - } - // If 0 < p < 1, return a null value - return self::$_errorCodes['null']; - } // function _inverse_ncdf() - - - private static function _inverse_ncdf2($prob) { - // Approximation of inverse standard normal CDF developed by - // B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58. - - $a1 = 2.50662823884; - $a2 = -18.61500062529; - $a3 = 41.39119773534; - $a4 = -25.44106049637; - - $b1 = -8.4735109309; - $b2 = 23.08336743743; - $b3 = -21.06224101826; - $b4 = 3.13082909833; - - $c1 = 0.337475482272615; - $c2 = 0.976169019091719; - $c3 = 0.160797971491821; - $c4 = 2.76438810333863E-02; - $c5 = 3.8405729373609E-03; - $c6 = 3.951896511919E-04; - $c7 = 3.21767881768E-05; - $c8 = 2.888167364E-07; - $c9 = 3.960315187E-07; - - $y = $prob - 0.5; - if (abs($y) < 0.42) { - $z = ($y * $y); - $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1); - } else { - if ($y > 0) { - $z = log(-log(1 - $prob)); - } else { - $z = log(-log($prob)); - } - $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9))))))); - if ($y < 0) { - $z = -$z; - } - } - return $z; - } // function _inverse_ncdf2() - - - private static function _inverse_ncdf3($p) { - // ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3. - // Produces the normal deviate Z corresponding to a given lower - // tail area of P; Z is accurate to about 1 part in 10**16. - // - // This is a PHP version of the original FORTRAN code that can - // be found at http://lib.stat.cmu.edu/apstat/ - $split1 = 0.425; - $split2 = 5; - $const1 = 0.180625; - $const2 = 1.6; - - // coefficients for p close to 0.5 - $a0 = 3.3871328727963666080; - $a1 = 1.3314166789178437745E+2; - $a2 = 1.9715909503065514427E+3; - $a3 = 1.3731693765509461125E+4; - $a4 = 4.5921953931549871457E+4; - $a5 = 6.7265770927008700853E+4; - $a6 = 3.3430575583588128105E+4; - $a7 = 2.5090809287301226727E+3; - - $b1 = 4.2313330701600911252E+1; - $b2 = 6.8718700749205790830E+2; - $b3 = 5.3941960214247511077E+3; - $b4 = 2.1213794301586595867E+4; - $b5 = 3.9307895800092710610E+4; - $b6 = 2.8729085735721942674E+4; - $b7 = 5.2264952788528545610E+3; - - // coefficients for p not close to 0, 0.5 or 1. - $c0 = 1.42343711074968357734; - $c1 = 4.63033784615654529590; - $c2 = 5.76949722146069140550; - $c3 = 3.64784832476320460504; - $c4 = 1.27045825245236838258; - $c5 = 2.41780725177450611770E-1; - $c6 = 2.27238449892691845833E-2; - $c7 = 7.74545014278341407640E-4; - - $d1 = 2.05319162663775882187; - $d2 = 1.67638483018380384940; - $d3 = 6.89767334985100004550E-1; - $d4 = 1.48103976427480074590E-1; - $d5 = 1.51986665636164571966E-2; - $d6 = 5.47593808499534494600E-4; - $d7 = 1.05075007164441684324E-9; - - // coefficients for p near 0 or 1. - $e0 = 6.65790464350110377720; - $e1 = 5.46378491116411436990; - $e2 = 1.78482653991729133580; - $e3 = 2.96560571828504891230E-1; - $e4 = 2.65321895265761230930E-2; - $e5 = 1.24266094738807843860E-3; - $e6 = 2.71155556874348757815E-5; - $e7 = 2.01033439929228813265E-7; - - $f1 = 5.99832206555887937690E-1; - $f2 = 1.36929880922735805310E-1; - $f3 = 1.48753612908506148525E-2; - $f4 = 7.86869131145613259100E-4; - $f5 = 1.84631831751005468180E-5; - $f6 = 1.42151175831644588870E-7; - $f7 = 2.04426310338993978564E-15; - - $q = $p - 0.5; - - // computation for p close to 0.5 - if (abs($q) <= split1) { - $R = $const1 - $q * $q; - $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) / - ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1); - } else { - if ($q < 0) { - $R = $p; - } else { - $R = 1 - $p; - } - $R = pow(-log($R),2); - - // computation for p not close to 0, 0.5 or 1. - If ($R <= $split2) { - $R = $R - $const2; - $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) / - ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1); - } else { - // computation for p near 0 or 1. - $R = $R - $split2; - $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) / - ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1); - } - if ($q < 0) { - $z = -$z; - } - } - return $z; - } // function _inverse_ncdf3() - - - /** - * NORMINV - * - * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation. - * - * @param float $value - * @param float $mean Mean Value - * @param float $stdDev Standard Deviation - * @return float - * - */ - public static function NORMINV($probability,$mean,$stdDev) { - $probability = self::flattenSingleValue($probability); - $mean = self::flattenSingleValue($mean); - $stdDev = self::flattenSingleValue($stdDev); - - if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) { - if (($probability < 0) || ($probability > 1)) { - return self::$_errorCodes['num']; - } - if ($stdDev < 0) { - return self::$_errorCodes['num']; - } - return (self::_inverse_ncdf($probability) * $stdDev) + $mean; - } - return self::$_errorCodes['value']; - } // function NORMINV() - - - /** - * NORMSINV - * - * Returns the inverse of the standard normal cumulative distribution - * - * @param float $value - * @return float - */ - public static function NORMSINV($value) { - return self::NORMINV($value, 0, 1); - } // function NORMSINV() - - - /** - * LOGINV - * - * Returns the inverse of the normal cumulative distribution - * - * @param float $value - * @return float - * - * @todo Try implementing P J Acklam's refinement algorithm for greater - * accuracy if I can get my head round the mathematics - * (as described at) http://home.online.no/~pjacklam/notes/invnorm/ - */ - public static function LOGINV($probability, $mean, $stdDev) { - $probability = self::flattenSingleValue($probability); - $mean = self::flattenSingleValue($mean); - $stdDev = self::flattenSingleValue($stdDev); - - if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) { - if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) { - return self::$_errorCodes['num']; - } - return exp($mean + $stdDev * self::NORMSINV($probability)); - } - return self::$_errorCodes['value']; - } // function LOGINV() - - - /** - * HYPGEOMDIST - * - * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of - * sample successes, given the sample size, population successes, and population size. - * - * @param float $sampleSuccesses Number of successes in the sample - * @param float $sampleNumber Size of the sample - * @param float $populationSuccesses Number of successes in the population - * @param float $populationNumber Population size - * @return float - * - */ - public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber) { - $sampleSuccesses = floor(self::flattenSingleValue($sampleSuccesses)); - $sampleNumber = floor(self::flattenSingleValue($sampleNumber)); - $populationSuccesses = floor(self::flattenSingleValue($populationSuccesses)); - $populationNumber = floor(self::flattenSingleValue($populationNumber)); - - if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) { - if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) { - return self::$_errorCodes['num']; - } - if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) { - return self::$_errorCodes['num']; - } - if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) { - return self::$_errorCodes['num']; - } - return self::COMBIN($populationSuccesses,$sampleSuccesses) * - self::COMBIN($populationNumber - $populationSuccesses,$sampleNumber - $sampleSuccesses) / - self::COMBIN($populationNumber,$sampleNumber); - } - return self::$_errorCodes['value']; - } // function HYPGEOMDIST() - - - /** - * TDIST - * - * Returns the probability of Student's T distribution. - * - * @param float $value Value for the function - * @param float $degrees degrees of freedom - * @param float $tails number of tails (1 or 2) - * @return float - */ - public static function TDIST($value, $degrees, $tails) { - $value = self::flattenSingleValue($value); - $degrees = floor(self::flattenSingleValue($degrees)); - $tails = floor(self::flattenSingleValue($tails)); - - if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) { - if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) { - return self::$_errorCodes['num']; - } - // tdist, which finds the probability that corresponds to a given value - // of t with k degrees of freedom. This algorithm is translated from a - // pascal function on p81 of "Statistical Computing in Pascal" by D - // Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd: - // London). The above Pascal algorithm is itself a translation of the - // fortran algoritm "AS 3" by B E Cooper of the Atlas Computer - // Laboratory as reported in (among other places) "Applied Statistics - // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis - // Horwood Ltd.; W. Sussex, England). - $tterm = $degrees; - $ttheta = atan2($value,sqrt($tterm)); - $tc = cos($ttheta); - $ts = sin($ttheta); - $tsum = 0; - - if (($degrees % 2) == 1) { - $ti = 3; - $tterm = $tc; - } else { - $ti = 2; - $tterm = 1; - } - - $tsum = $tterm; - while ($ti < $degrees) { - $tterm *= $tc * $tc * ($ti - 1) / $ti; - $tsum += $tterm; - $ti += 2; - } - $tsum *= $ts; - if (($degrees % 2) == 1) { $tsum = M_2DIVPI * ($tsum + $ttheta); } - $tValue = 0.5 * (1 + $tsum); - if ($tails == 1) { - return 1 - abs($tValue); - } else { - return 1 - abs((1 - $tValue) - $tValue); - } - } - return self::$_errorCodes['value']; - } // function TDIST() - - - /** - * TINV - * - * Returns the one-tailed probability of the chi-squared distribution. - * - * @param float $probability Probability for the function - * @param float $degrees degrees of freedom - * @return float - */ - public static function TINV($probability, $degrees) { - $probability = self::flattenSingleValue($probability); - $degrees = floor(self::flattenSingleValue($degrees)); - - if ((is_numeric($probability)) && (is_numeric($degrees))) { - $xLo = 100; - $xHi = 0; - - $x = $xNew = 1; - $dx = 1; - $i = 0; - - while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { - // Apply Newton-Raphson step - $result = self::TDIST($x, $degrees, 2); - $error = $result - $probability; - if ($error == 0.0) { - $dx = 0; - } elseif ($error < 0.0) { - $xLo = $x; - } else { - $xHi = $x; - } - // Avoid division by zero - if ($result != 0.0) { - $dx = $error / $result; - $xNew = $x - $dx; - } - // If the NR fails to converge (which for example may be the - // case if the initial guess is too rough) we apply a bisection - // step to determine a more narrow interval around the root. - if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { - $xNew = ($xLo + $xHi) / 2; - $dx = $xNew - $x; - } - $x = $xNew; - } - if ($i == MAX_ITERATIONS) { - return self::$_errorCodes['na']; - } - return round($x,12); - } - return self::$_errorCodes['value']; - } // function TINV() - - - /** - * CONFIDENCE - * - * Returns the confidence interval for a population mean - * - * @param float $alpha - * @param float $stdDev Standard Deviation - * @param float $size - * @return float - * - */ - public static function CONFIDENCE($alpha,$stdDev,$size) { - $alpha = self::flattenSingleValue($alpha); - $stdDev = self::flattenSingleValue($stdDev); - $size = floor(self::flattenSingleValue($size)); - - if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) { - if (($alpha <= 0) || ($alpha >= 1)) { - return self::$_errorCodes['num']; - } - if (($stdDev <= 0) || ($size < 1)) { - return self::$_errorCodes['num']; - } - return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size); - } - return self::$_errorCodes['value']; - } // function CONFIDENCE() - - - /** - * POISSON - * - * Returns the Poisson distribution. A common application of the Poisson distribution - * is predicting the number of events over a specific time, such as the number of - * cars arriving at a toll plaza in 1 minute. - * - * @param float $value - * @param float $mean Mean Value - * @param boolean $cumulative - * @return float - * - */ - public static function POISSON($value, $mean, $cumulative) { - $value = self::flattenSingleValue($value); - $mean = self::flattenSingleValue($mean); - - if ((is_numeric($value)) && (is_numeric($mean))) { - if (($value <= 0) || ($mean <= 0)) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - $summer = 0; - for ($i = 0; $i <= floor($value); ++$i) { - $summer += pow($mean,$i) / self::FACT($i); - } - return exp(0-$mean) * $summer; - } else { - return (exp(0-$mean) * pow($mean,$value)) / self::FACT($value); - } - } - } - return self::$_errorCodes['value']; - } // function POISSON() - - - /** - * WEIBULL - * - * Returns the Weibull distribution. Use this distribution in reliability - * analysis, such as calculating a device's mean time to failure. - * - * @param float $value - * @param float $alpha Alpha Parameter - * @param float $beta Beta Parameter - * @param boolean $cumulative - * @return float - * - */ - public static function WEIBULL($value, $alpha, $beta, $cumulative) { - $value = self::flattenSingleValue($value); - $alpha = self::flattenSingleValue($alpha); - $beta = self::flattenSingleValue($beta); - - if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) { - if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) { - return self::$_errorCodes['num']; - } - if ((is_numeric($cumulative)) || (is_bool($cumulative))) { - if ($cumulative) { - return 1 - exp(0 - pow($value / $beta,$alpha)); - } else { - return ($alpha / pow($beta,$alpha)) * pow($value,$alpha - 1) * exp(0 - pow($value / $beta,$alpha)); - } - } - } - return self::$_errorCodes['value']; - } // function WEIBULL() - - - /** - * ZTEST - * - * Returns the Weibull distribution. Use this distribution in reliability - * analysis, such as calculating a device's mean time to failure. - * - * @param float $value - * @param float $alpha Alpha Parameter - * @param float $beta Beta Parameter - * @param boolean $cumulative - * @return float - * - */ - public static function ZTEST($dataSet, $m0, $sigma=null) { - $dataSet = self::flattenArrayIndexed($dataSet); - $m0 = self::flattenSingleValue($m0); - $sigma = self::flattenSingleValue($sigma); - - if (is_null($sigma)) { - $sigma = self::STDEV($dataSet); - } - $n = count($dataSet); - - return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0)/($sigma/SQRT($n))); - } // function ZTEST() - - - /** - * SKEW - * - * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry - * of a distribution around its mean. Positive skewness indicates a distribution with an - * asymmetric tail extending toward more positive values. Negative skewness indicates a - * distribution with an asymmetric tail extending toward more negative values. - * - * @param array Data Series - * @return float - */ - public static function SKEW() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - $mean = self::AVERAGE($aArgs); - $stdDev = self::STDEV($aArgs); - - $count = $summer = 0; - // Loop through arguments - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - (!self::isMatrixValue($k))) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),3) ; - ++$count; - } - } - } - - // Return - if ($count > 2) { - return $summer * ($count / (($count-1) * ($count-2))); - } - return self::$_errorCodes['divisionbyzero']; - } // function SKEW() - - - /** - * KURT - * - * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness - * or flatness of a distribution compared with the normal distribution. Positive - * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a - * relatively flat distribution. - * - * @param array Data Series - * @return float - */ - public static function KURT() { - $aArgs = self::flattenArrayIndexed(func_get_args()); - $mean = self::AVERAGE($aArgs); - $stdDev = self::STDEV($aArgs); - - if ($stdDev > 0) { - $count = $summer = 0; - // Loop through arguments - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - (!self::isMatrixValue($k))) { - } else { - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - $summer += pow((($arg - $mean) / $stdDev),4) ; - ++$count; - } - } - } - - // Return - if ($count > 3) { - return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1,2) / (($count-2) * ($count-3))); - } - } - return self::$_errorCodes['divisionbyzero']; - } // function KURT() - - - /** - * RAND - * - * @param int $min Minimal value - * @param int $max Maximal value - * @return int Random number - */ - public static function RAND($min = 0, $max = 0) { - $min = self::flattenSingleValue($min); - $max = self::flattenSingleValue($max); - - if ($min == 0 && $max == 0) { - return (rand(0,10000000)) / 10000000; - } else { - return rand($min, $max); - } - } // function RAND() - - - /** - * MOD - * - * @param int $a Dividend - * @param int $b Divisor - * @return int Remainder - */ - public static function MOD($a = 1, $b = 1) { - $a = self::flattenSingleValue($a); - $b = self::flattenSingleValue($b); - - if ($b == 0.0) { - return self::$_errorCodes['divisionbyzero']; - } elseif (($a < 0.0) && ($b > 0.0)) { - return $b - fmod(abs($a),$b); - } elseif (($a > 0.0) && ($b < 0.0)) { - return $b + fmod($a,abs($b)); - } - - return fmod($a,$b); - } // function MOD() - - - /** - * CHARACTER - * - * @param string $character Value - * @return int - */ - public static function CHARACTER($character) { - $character = self::flattenSingleValue($character); - - if ((!is_numeric($character)) || ($character < 0)) { - return self::$_errorCodes['value']; - } - - if (function_exists('mb_convert_encoding')) { - return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); - } else { - return chr(intval($character)); - } - } - - - private static function _uniord($c) { - if (ord($c{0}) >=0 && ord($c{0}) <= 127) - return ord($c{0}); - if (ord($c{0}) >= 192 && ord($c{0}) <= 223) - return (ord($c{0})-192)*64 + (ord($c{1})-128); - if (ord($c{0}) >= 224 && ord($c{0}) <= 239) - return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); - if (ord($c{0}) >= 240 && ord($c{0}) <= 247) - return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); - if (ord($c{0}) >= 248 && ord($c{0}) <= 251) - return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); - if (ord($c{0}) >= 252 && ord($c{0}) <= 253) - return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); - if (ord($c{0}) >= 254 && ord($c{0}) <= 255) //error - return self::$_errorCodes['value']; - return 0; - } // function _uniord() - - /** - * ASCIICODE - * - * @param string $character Value - * @return int - */ - public static function ASCIICODE($characters) { - $characters = self::flattenSingleValue($characters); - if (is_bool($characters)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $characters = (int) $characters; - } else { - if ($characters) { - $characters = 'True'; - } else { - $characters = 'False'; - } - } - } - - $character = $characters; - if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { - if (mb_strlen($characters, 'UTF-8') > 1) { $character = mb_substr($characters, 0, 1, 'UTF-8'); } - return self::_uniord($character); - } else { - if (strlen($characters) > 0) { $character = substr($characters, 0, 1); } - return ord($character); - } - } // function ASCIICODE() - - - /** - * CONCATENATE - * - * @return string - */ - public static function CONCATENATE() { - // Return value - $returnValue = ''; - - // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - foreach ($aArgs as $arg) { - if (is_bool($arg)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $arg = (int) $arg; - } else { - if ($arg) { - $arg = 'TRUE'; - } else { - $arg = 'FALSE'; - } - } - } - $returnValue .= $arg; - } - - // Return - return $returnValue; - } // function CONCATENATE() - - - /** - * STRINGLENGTH - * - * @param string $value Value - * @param int $chars Number of characters - * @return string - */ - public static function STRINGLENGTH($value = '') { - $value = self::flattenSingleValue($value); - - if (is_bool($value)) { - $value = ($value) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_strlen')) { - return mb_strlen($value, 'UTF-8'); - } else { - return strlen($value); - } - } // function STRINGLENGTH() - - - /** - * SEARCHSENSITIVE - * - * @param string $needle The string to look for - * @param string $haystack The string in which to look - * @param int $offset Offset within $haystack - * @return string - */ - public static function SEARCHSENSITIVE($needle,$haystack,$offset=1) { - $needle = self::flattenSingleValue($needle); - $haystack = self::flattenSingleValue($haystack); - $offset = self::flattenSingleValue($offset); - - if (!is_bool($needle)) { - if (is_bool($haystack)) { - $haystack = ($haystack) ? 'TRUE' : 'FALSE'; - } - - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_strpos')) { - $pos = mb_strpos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = strpos($haystack, $needle, --$offset); - } - if ($pos !== false) { - return ++$pos; - } - } - } - return self::$_errorCodes['value']; - } // function SEARCHSENSITIVE() - - - /** - * SEARCHINSENSITIVE - * - * @param string $needle The string to look for - * @param string $haystack The string in which to look - * @param int $offset Offset within $haystack - * @return string - */ - public static function SEARCHINSENSITIVE($needle,$haystack,$offset=1) { - $needle = self::flattenSingleValue($needle); - $haystack = self::flattenSingleValue($haystack); - $offset = self::flattenSingleValue($offset); - - if (!is_bool($needle)) { - if (is_bool($haystack)) { - $haystack = ($haystack) ? 'TRUE' : 'FALSE'; - } - - if (($offset > 0) && (strlen($haystack) > $offset)) { - if (function_exists('mb_stripos')) { - $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); - } else { - $pos = stripos($haystack, $needle, --$offset); - } - if ($pos !== false) { - return ++$pos; - } - } - } - return self::$_errorCodes['value']; - } // function SEARCHINSENSITIVE() - - - /** - * LEFT - * - * @param string $value Value - * @param int $chars Number of characters - * @return string - */ - public static function LEFT($value = '', $chars = 1) { - $value = self::flattenSingleValue($value); - $chars = self::flattenSingleValue($chars); - - if ($chars < 0) { - return self::$_errorCodes['value']; - } - - if (is_bool($value)) { - $value = ($value) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_substr')) { - return mb_substr($value, 0, $chars, 'UTF-8'); - } else { - return substr($value, 0, $chars); - } - } // function LEFT() - - - /** - * RIGHT - * - * @param string $value Value - * @param int $chars Number of characters - * @return string - */ - public static function RIGHT($value = '', $chars = 1) { - $value = self::flattenSingleValue($value); - $chars = self::flattenSingleValue($chars); - - if ($chars < 0) { - return self::$_errorCodes['value']; - } - - if (is_bool($value)) { - $value = ($value) ? 'TRUE' : 'FALSE'; - } - - if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { - return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); - } else { - return substr($value, strlen($value) - $chars); - } - } // function RIGHT() - - - /** - * MID - * - * @param string $value Value - * @param int $start Start character - * @param int $chars Number of characters - * @return string - */ - public static function MID($value = '', $start = 1, $chars = null) { - $value = self::flattenSingleValue($value); - $start = self::flattenSingleValue($start); - $chars = self::flattenSingleValue($chars); - - if (($start < 1) || ($chars < 0)) { - return self::$_errorCodes['value']; - } - - if (is_bool($value)) { - $value = ($value) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_substr')) { - return mb_substr($value, --$start, $chars, 'UTF-8'); - } else { - return substr($value, --$start, $chars); - } - } // function MID() - - - /** - * REPLACE - * - * @param string $value Value - * @param int $start Start character - * @param int $chars Number of characters - * @return string - */ - public static function REPLACE($oldText = '', $start = 1, $chars = null, $newText) { - $oldText = self::flattenSingleValue($oldText); - $start = self::flattenSingleValue($start); - $chars = self::flattenSingleValue($chars); - $newText = self::flattenSingleValue($newText); - - $left = self::LEFT($oldText,$start-1); - $right = self::RIGHT($oldText,self::STRINGLENGTH($oldText)-($start+$chars)+1); - - return $left.$newText.$right; - } // function REPLACE() - - - /** - * SUBSTITUTE - * - * @param string $text Value - * @param string $fromText From Value - * @param string $toText To Value - * @param integer $instance Instance Number - * @return string - */ - public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) { - $text = self::flattenSingleValue($text); - $fromText = self::flattenSingleValue($fromText); - $toText = self::flattenSingleValue($toText); - $instance = floor(self::flattenSingleValue($instance)); - - if ($instance == 0) { - if(function_exists('mb_str_replace')) { - return mb_str_replace($fromText,$toText,$text); - } else { - return str_replace($fromText,$toText,$text); - } - } else { - $pos = -1; - while($instance > 0) { - if (function_exists('mb_strpos')) { - $pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); - } else { - $pos = strpos($text, $fromText, $pos+1); - } - if ($pos === false) { - break; - } - --$instance; - } - if ($pos !== false) { - if (function_exists('mb_strlen')) { - return self::REPLACE($text,++$pos,mb_strlen($fromText, 'UTF-8'),$toText); - } else { - return self::REPLACE($text,++$pos,strlen($fromText),$toText); - } - } - } - - return $left.$newText.$right; - } // function SUBSTITUTE() - - - /** - * RETURNSTRING - * - * @param mixed $value Value to check - * @return boolean - */ - public static function RETURNSTRING($testValue = '') { - $testValue = self::flattenSingleValue($testValue); - - if (is_string($testValue)) { - return $testValue; - } - return Null; - } // function RETURNSTRING() - - - /** - * FIXEDFORMAT - * - * @param mixed $value Value to check - * @return boolean - */ - public static function FIXEDFORMAT($value,$decimals=2,$no_commas=false) { - $value = self::flattenSingleValue($value); - $decimals = self::flattenSingleValue($decimals); - $no_commas = self::flattenSingleValue($no_commas); - - $valueResult = round($value,$decimals); - if ($decimals < 0) { $decimals = 0; } - if (!$no_commas) { - $valueResult = number_format($valueResult,$decimals); - } - - return (string) $valueResult; - } // function FIXEDFORMAT() - - - /** - * TEXTFORMAT - * - * @param mixed $value Value to check - * @return boolean - */ - public static function TEXTFORMAT($value,$format) { - $value = self::flattenSingleValue($value); - $format = self::flattenSingleValue($format); - - if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { - $value = self::DATEVALUE($value); - } - - return (string) PHPExcel_Style_NumberFormat::toFormattedString($value,$format); - } // function TEXTFORMAT() - - - /** - * TRIMSPACES - * - * @param mixed $value Value to check - * @return string - */ - public static function TRIMSPACES($stringValue = '') { - $stringValue = self::flattenSingleValue($stringValue); - - if (is_string($stringValue) || is_numeric($stringValue)) { - return trim(preg_replace('/ +/',' ',$stringValue)); - } - return Null; - } // function TRIMSPACES() - - - private static $_invalidChars = Null; - - /** - * TRIMNONPRINTABLE - * - * @param mixed $value Value to check - * @return string - */ - public static function TRIMNONPRINTABLE($stringValue = '') { - $stringValue = self::flattenSingleValue($stringValue); - - if (is_bool($stringValue)) { - $stringValue = ($stringValue) ? 'TRUE' : 'FALSE'; - } - - if (self::$_invalidChars == Null) { - self::$_invalidChars = range(chr(0),chr(31)); - } - - if (is_string($stringValue) || is_numeric($stringValue)) { - return str_replace(self::$_invalidChars,'',trim($stringValue,"\x00..\x1F")); - } - return Null; - } // function TRIMNONPRINTABLE() - /** * ERROR_TYPE @@ -5617,7 +423,7 @@ class PHPExcel_Calculation_Functions { * @return boolean */ public static function IS_ODD($value = null) { - $value = self::flattenSingleValue($value); + $value = self::flattenSingleValue($value); if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) { return self::$_errorCodes['value']; @@ -5689,5606 +495,6 @@ class PHPExcel_Calculation_Functions { } // function VERSION() - /** - * DATE - * - * @param long $year - * @param long $month - * @param long $day - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function DATE($year = 0, $month = 1, $day = 1) { - $year = (integer) self::flattenSingleValue($year); - $month = (integer) self::flattenSingleValue($month); - $day = (integer) self::flattenSingleValue($day); - - $baseYear = PHPExcel_Shared_Date::getExcelCalendar(); - // Validate parameters - if ($year < ($baseYear-1900)) { - return self::$_errorCodes['num']; - } - if ((($baseYear-1900) != 0) && ($year < $baseYear) && ($year >= 1900)) { - return self::$_errorCodes['num']; - } - - if (($year < $baseYear) && ($year >= ($baseYear-1900))) { - $year += 1900; - } - - if ($month < 1) { - // Handle year/month adjustment if month < 1 - --$month; - $year += ceil($month / 12) - 1; - $month = 13 - abs($month % 12); - } elseif ($month > 12) { - // Handle year/month adjustment if month > 12 - $year += floor($month / 12); - $month = ($month % 12); - } - - // Re-validate the year parameter after adjustments - if (($year < $baseYear) || ($year >= 10000)) { - return self::$_errorCodes['num']; - } - - // Execute function - $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year, $month, $day); - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) $excelDateValue; - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateValue); - break; - case self::RETURNDATE_PHP_OBJECT : return PHPExcel_Shared_Date::ExcelToPHPObject($excelDateValue); - break; - } - } // function DATE() - - - /** - * TIME - * - * @param long $hour - * @param long $minute - * @param long $second - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function TIME($hour = 0, $minute = 0, $second = 0) { - $hour = self::flattenSingleValue($hour); - $minute = self::flattenSingleValue($minute); - $second = self::flattenSingleValue($second); - - if ($hour == '') { $hour = 0; } - if ($minute == '') { $minute = 0; } - if ($second == '') { $second = 0; } - - if ((!is_numeric($hour)) || (!is_numeric($minute)) || (!is_numeric($second))) { - return self::$_errorCodes['value']; - } - $hour = (integer) $hour; - $minute = (integer) $minute; - $second = (integer) $second; - - if ($second < 0) { - $minute += floor($second / 60); - $second = 60 - abs($second % 60); - if ($second == 60) { $second = 0; } - } elseif ($second >= 60) { - $minute += floor($second / 60); - $second = $second % 60; - } - if ($minute < 0) { - $hour += floor($minute / 60); - $minute = 60 - abs($minute % 60); - if ($minute == 60) { $minute = 0; } - } elseif ($minute >= 60) { - $hour += floor($minute / 60); - $minute = $minute % 60; - } - - if ($hour > 23) { - $hour = $hour % 24; - } elseif ($hour < 0) { - return self::$_errorCodes['num']; - } - - // Execute function - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : $date = 0; - $calendar = PHPExcel_Shared_Date::getExcelCalendar(); - if ($calendar != PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900) { - $date = 1; - } - return (float) PHPExcel_Shared_Date::FormattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second); - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::FormattedPHPToExcel(1970, 1, 1, $hour-1, $minute, $second)); // -2147468400; // -2147472000 + 3600 - break; - case self::RETURNDATE_PHP_OBJECT : $dayAdjust = 0; - if ($hour < 0) { - $dayAdjust = floor($hour / 24); - $hour = 24 - abs($hour % 24); - if ($hour == 24) { $hour = 0; } - } elseif ($hour >= 24) { - $dayAdjust = floor($hour / 24); - $hour = $hour % 24; - } - $phpDateObject = new DateTime('1900-01-01 '.$hour.':'.$minute.':'.$second); - if ($dayAdjust != 0) { - $phpDateObject->modify($dayAdjust.' days'); - } - return $phpDateObject; - break; - } - } // function TIME() - - - /** - * DATEVALUE - * - * @param string $dateValue - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function DATEVALUE($dateValue = 1) { - $dateValue = trim(self::flattenSingleValue($dateValue),'"'); - // Strip any ordinals because they're allowed in Excel (English only) - $dateValue = preg_replace('/(\d)(st|nd|rd|th)([ -\/])/Ui','$1$3',$dateValue); - // Convert separators (/ . or space) to hyphens (should also handle dot used for ordinals in some countries, e.g. Denmark, Germany) - $dateValue = str_replace(array('/','.','-',' '),array(' ',' ',' ',' '),$dateValue); - - $yearFound = false; - $t1 = explode(' ',$dateValue); - foreach($t1 as &$t) { - if ((is_numeric($t)) && ($t > 31)) { - if ($yearFound) { - return self::$_errorCodes['value']; - } else { - if ($t < 100) { $t += 1900; } - $yearFound = true; - } - } - } - if ((count($t1) == 1) && (strpos($t,':') != false)) { - // We've been fed a time value without any date - return 0.0; - } elseif (count($t1) == 2) { - // We only have two parts of the date: either day/month or month/year - if ($yearFound) { - array_unshift($t1,1); - } else { - array_push($t1,date('Y')); - } - } - unset($t); - $dateValue = implode(' ',$t1); - - $PHPDateArray = date_parse($dateValue); - if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { - $testVal1 = strtok($dateValue,'- '); - if ($testVal1 !== False) { - $testVal2 = strtok('- '); - if ($testVal2 !== False) { - $testVal3 = strtok('- '); - if ($testVal3 === False) { - $testVal3 = strftime('%Y'); - } - } else { - return self::$_errorCodes['value']; - } - } else { - return self::$_errorCodes['value']; - } - $PHPDateArray = date_parse($testVal1.'-'.$testVal2.'-'.$testVal3); - if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { - $PHPDateArray = date_parse($testVal2.'-'.$testVal1.'-'.$testVal3); - if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { - return self::$_errorCodes['value']; - } - } - } - - if (($PHPDateArray !== False) && ($PHPDateArray['error_count'] == 0)) { - // Execute function - if ($PHPDateArray['year'] == '') { $PHPDateArray['year'] = strftime('%Y'); } - if ($PHPDateArray['month'] == '') { $PHPDateArray['month'] = strftime('%m'); } - if ($PHPDateArray['day'] == '') { $PHPDateArray['day'] = strftime('%d'); } - $excelDateValue = floor(PHPExcel_Shared_Date::FormattedPHPToExcel($PHPDateArray['year'],$PHPDateArray['month'],$PHPDateArray['day'],$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second'])); - - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) $excelDateValue; - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateValue); - break; - case self::RETURNDATE_PHP_OBJECT : return new DateTime($PHPDateArray['year'].'-'.$PHPDateArray['month'].'-'.$PHPDateArray['day'].' 00:00:00'); - break; - } - } - return self::$_errorCodes['value']; - } // function DATEVALUE() - - - /** - * _getDateValue - * - * @param string $dateValue - * @return mixed Excel date/time serial value, or string if error - */ - private static function _getDateValue($dateValue) { - if (!is_numeric($dateValue)) { - if ((is_string($dateValue)) && (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC)) { - return self::$_errorCodes['value']; - } - if ((is_object($dateValue)) && ($dateValue instanceof PHPExcel_Shared_Date::$dateTimeObjectType)) { - $dateValue = PHPExcel_Shared_Date::PHPToExcel($dateValue); - } else { - $saveReturnDateType = self::getReturnDateType(); - self::setReturnDateType(self::RETURNDATE_EXCEL); - $dateValue = self::DATEVALUE($dateValue); - self::setReturnDateType($saveReturnDateType); - } - } - return $dateValue; - } // function _getDateValue() - - - /** - * TIMEVALUE - * - * @param string $timeValue - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function TIMEVALUE($timeValue) { - $timeValue = trim(self::flattenSingleValue($timeValue),'"'); - $timeValue = str_replace(array('/','.'),array('-','-'),$timeValue); - - $PHPDateArray = date_parse($timeValue); - if (($PHPDateArray !== False) && ($PHPDateArray['error_count'] == 0)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($PHPDateArray['year'],$PHPDateArray['month'],$PHPDateArray['day'],$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second']); - } else { - $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel(1900,1,1,$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second']) - 1; - } - - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) $excelDateValue; - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) $phpDateValue = PHPExcel_Shared_Date::ExcelToPHP($excelDateValue+25569) - 3600;; - break; - case self::RETURNDATE_PHP_OBJECT : return new DateTime('1900-01-01 '.$PHPDateArray['hour'].':'.$PHPDateArray['minute'].':'.$PHPDateArray['second']); - break; - } - } - return self::$_errorCodes['value']; - } // function TIMEVALUE() - - - /** - * _getTimeValue - * - * @param string $timeValue - * @return mixed Excel date/time serial value, or string if error - */ - private static function _getTimeValue($timeValue) { - $saveReturnDateType = self::getReturnDateType(); - self::setReturnDateType(self::RETURNDATE_EXCEL); - $timeValue = self::TIMEVALUE($timeValue); - self::setReturnDateType($saveReturnDateType); - return $timeValue; - } // function _getTimeValue() - - - /** - * DATETIMENOW - * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function DATETIMENOW() { - $saveTimeZone = date_default_timezone_get(); - date_default_timezone_set('UTC'); - $retValue = False; - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : $retValue = (float) PHPExcel_Shared_Date::PHPToExcel(time()); - break; - case self::RETURNDATE_PHP_NUMERIC : $retValue = (integer) time(); - break; - case self::RETURNDATE_PHP_OBJECT : $retValue = new DateTime(); - break; - } - date_default_timezone_set($saveTimeZone); - - return $retValue; - } // function DATETIMENOW() - - - /** - * DATENOW - * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, - * depending on the value of the ReturnDateType flag - */ - public static function DATENOW() { - $saveTimeZone = date_default_timezone_get(); - date_default_timezone_set('UTC'); - $retValue = False; - $excelDateTime = floor(PHPExcel_Shared_Date::PHPToExcel(time())); - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : $retValue = (float) $excelDateTime; - break; - case self::RETURNDATE_PHP_NUMERIC : $retValue = (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateTime) - 3600; - break; - case self::RETURNDATE_PHP_OBJECT : $retValue = PHPExcel_Shared_Date::ExcelToPHPObject($excelDateTime); - break; - } - date_default_timezone_set($saveTimeZone); - - return $retValue; - } // function DATENOW() - - - private static function _isLeapYear($year) { - return ((($year % 4) == 0) && (($year % 100) != 0) || (($year % 400) == 0)); - } // function _isLeapYear() - - - private static function _dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, $methodUS) { - if ($startDay == 31) { - --$startDay; - } elseif ($methodUS && ($startMonth == 2 && ($startDay == 29 || ($startDay == 28 && !self::_isLeapYear($startYear))))) { - $startDay = 30; - } - if ($endDay == 31) { - if ($methodUS && $startDay != 30) { - $endDay = 1; - if ($endMonth == 12) { - ++$endYear; - $endMonth = 1; - } else { - ++$endMonth; - } - } else { - $endDay = 30; - } - } - - return $endDay + $endMonth * 30 + $endYear * 360 - $startDay - $startMonth * 30 - $startYear * 360; - } // function _dateDiff360() - - - /** - * DAYS360 - * - * @param long $startDate Excel date serial value or a standard date string - * @param long $endDate Excel date serial value or a standard date string - * @param boolean $method US or European Method - * @return long PHP date/time serial - */ - public static function DAYS360($startDate = 0, $endDate = 0, $method = false) { - $startDate = self::flattenSingleValue($startDate); - $endDate = self::flattenSingleValue($endDate); - - if (is_string($startDate = self::_getDateValue($startDate))) { - return self::$_errorCodes['value']; - } - if (is_string($endDate = self::_getDateValue($endDate))) { - return self::$_errorCodes['value']; - } - - // Execute function - $PHPStartDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($startDate); - $startDay = $PHPStartDateObject->format('j'); - $startMonth = $PHPStartDateObject->format('n'); - $startYear = $PHPStartDateObject->format('Y'); - - $PHPEndDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($endDate); - $endDay = $PHPEndDateObject->format('j'); - $endMonth = $PHPEndDateObject->format('n'); - $endYear = $PHPEndDateObject->format('Y'); - - return self::_dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, !$method); - } // function DAYS360() - - - /** - * DATEDIF - * - * @param long $startDate Excel date serial value or a standard date string - * @param long $endDate Excel date serial value or a standard date string - * @param string $unit - * @return long Interval between the dates - */ - public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') { - $startDate = self::flattenSingleValue($startDate); - $endDate = self::flattenSingleValue($endDate); - $unit = strtoupper(self::flattenSingleValue($unit)); - - if (is_string($startDate = self::_getDateValue($startDate))) { - return self::$_errorCodes['value']; - } - if (is_string($endDate = self::_getDateValue($endDate))) { - return self::$_errorCodes['value']; - } - - // Validate parameters - if ($startDate >= $endDate) { - return self::$_errorCodes['num']; - } - - // Execute function - $difference = $endDate - $startDate; - - $PHPStartDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($startDate); - $startDays = $PHPStartDateObject->format('j'); - $startMonths = $PHPStartDateObject->format('n'); - $startYears = $PHPStartDateObject->format('Y'); - - $PHPEndDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($endDate); - $endDays = $PHPEndDateObject->format('j'); - $endMonths = $PHPEndDateObject->format('n'); - $endYears = $PHPEndDateObject->format('Y'); - - $retVal = self::$_errorCodes['num']; - switch ($unit) { - case 'D': - $retVal = intval($difference); - break; - case 'M': - $retVal = intval($endMonths - $startMonths) + (intval($endYears - $startYears) * 12); - // We're only interested in full months - if ($endDays < $startDays) { - --$retVal; - } - break; - case 'Y': - $retVal = intval($endYears - $startYears); - // We're only interested in full months - if ($endMonths < $startMonths) { - --$retVal; - } elseif (($endMonths == $startMonths) && ($endDays < $startDays)) { - --$retVal; - } - break; - case 'MD': - if ($endDays < $startDays) { - $retVal = $endDays; - $PHPEndDateObject->modify('-'.$endDays.' days'); - $adjustDays = $PHPEndDateObject->format('j'); - if ($adjustDays > $startDays) { - $retVal += ($adjustDays - $startDays); - } - } else { - $retVal = $endDays - $startDays; - } - break; - case 'YM': - $retVal = intval($endMonths - $startMonths); - if ($retVal < 0) $retVal = 12 + $retVal; - // We're only interested in full months - if ($endDays < $startDays) { - --$retVal; - } - break; - case 'YD': - $retVal = intval($difference); - if ($endYears > $startYears) { - while ($endYears > $startYears) { - $PHPEndDateObject->modify('-1 year'); - $endYears = $PHPEndDateObject->format('Y'); - } - $retVal = $PHPEndDateObject->format('z') - $PHPStartDateObject->format('z'); - if ($retVal < 0) { $retVal += 365; } - } - break; - } - return $retVal; - } // function DATEDIF() - - - /** - * YEARFRAC - * - * Calculates the fraction of the year represented by the number of whole days between two dates (the start_date and the - * end_date). Use the YEARFRAC worksheet function to identify the proportion of a whole year's benefits or obligations - * to assign to a specific term. - * - * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer) or date object, or a standard date string - * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer) or date object, or a standard date string - * @param integer $method Method used for the calculation - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float fraction of the year - */ - public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { - $startDate = self::flattenSingleValue($startDate); - $endDate = self::flattenSingleValue($endDate); - $method = self::flattenSingleValue($method); - - if (is_string($startDate = self::_getDateValue($startDate))) { - return self::$_errorCodes['value']; - } - if (is_string($endDate = self::_getDateValue($endDate))) { - return self::$_errorCodes['value']; - } - - if (((is_numeric($method)) && (!is_string($method))) || ($method == '')) { - switch($method) { - case 0 : - return self::DAYS360($startDate,$endDate) / 360; - break; - case 1 : - $days = self::DATEDIF($startDate,$endDate); - $startYear = self::YEAR($startDate); - $endYear = self::YEAR($endDate); - $years = $endYear - $startYear + 1; - $leapDays = 0; - if ($years == 1) { - if (self::_isLeapYear($endYear)) { - $startMonth = self::MONTHOFYEAR($startDate); - $endMonth = self::MONTHOFYEAR($endDate); - $endDay = self::DAYOFMONTH($endDate); - if (($startMonth < 3) || - (($endMonth * 100 + $endDay) >= (2 * 100 + 29))) { - $leapDays += 1; - } - } - } else { - for($year = $startYear; $year <= $endYear; ++$year) { - if ($year == $startYear) { - $startMonth = self::MONTHOFYEAR($startDate); - $startDay = self::DAYOFMONTH($startDate); - if ($startMonth < 3) { - $leapDays += (self::_isLeapYear($year)) ? 1 : 0; - } - } elseif($year == $endYear) { - $endMonth = self::MONTHOFYEAR($endDate); - $endDay = self::DAYOFMONTH($endDate); - if (($endMonth * 100 + $endDay) >= (2 * 100 + 29)) { - $leapDays += (self::_isLeapYear($year)) ? 1 : 0; - } - } else { - $leapDays += (self::_isLeapYear($year)) ? 1 : 0; - } - } - if ($years == 2) { - if (($leapDays == 0) && (self::_isLeapYear($startYear)) && ($days > 365)) { - $leapDays = 1; - } elseif ($days < 366) { - $years = 1; - } - } - $leapDays /= $years; - } - return $days / (365 + $leapDays); - break; - case 2 : - return self::DATEDIF($startDate,$endDate) / 360; - break; - case 3 : - return self::DATEDIF($startDate,$endDate) / 365; - break; - case 4 : - return self::DAYS360($startDate,$endDate,True) / 360; - break; - } - } - return self::$_errorCodes['value']; - } // function YEARFRAC() - - - /** - * NETWORKDAYS - * - * @param mixed Start date - * @param mixed End date - * @param array of mixed Optional Date Series - * @return long Interval between the dates - */ - public static function NETWORKDAYS($startDate,$endDate) { - // Retrieve the mandatory start and end date that are referenced in the function definition - $startDate = self::flattenSingleValue($startDate); - $endDate = self::flattenSingleValue($endDate); - // Flush the mandatory start and end date that are referenced in the function definition, and get the optional days - $dateArgs = self::flattenArray(func_get_args()); - array_shift($dateArgs); - array_shift($dateArgs); - - // Validate the start and end dates - if (is_string($startDate = $sDate = self::_getDateValue($startDate))) { - return self::$_errorCodes['value']; - } - $startDate = (float) floor($startDate); - if (is_string($endDate = $eDate = self::_getDateValue($endDate))) { - return self::$_errorCodes['value']; - } - $endDate = (float) floor($endDate); - - if ($sDate > $eDate) { - $startDate = $eDate; - $endDate = $sDate; - } - - // Execute function - $startDoW = 6 - self::DAYOFWEEK($startDate,2); - if ($startDoW < 0) { $startDoW = 0; } - $endDoW = self::DAYOFWEEK($endDate,2); - if ($endDoW >= 6) { $endDoW = 0; } - - $wholeWeekDays = floor(($endDate - $startDate) / 7) * 5; - $partWeekDays = $endDoW + $startDoW; - if ($partWeekDays > 5) { - $partWeekDays -= 5; - } - - // Test any extra holiday parameters - $holidayCountedArray = array(); - foreach ($dateArgs as $holidayDate) { - if (is_string($holidayDate = self::_getDateValue($holidayDate))) { - return self::$_errorCodes['value']; - } - if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { - if ((self::DAYOFWEEK($holidayDate,2) < 6) && (!in_array($holidayDate,$holidayCountedArray))) { - --$partWeekDays; - $holidayCountedArray[] = $holidayDate; - } - } - } - - if ($sDate > $eDate) { - return 0 - ($wholeWeekDays + $partWeekDays); - } - return $wholeWeekDays + $partWeekDays; - } // function NETWORKDAYS() - - - /** - * WORKDAY - * - * @param mixed Start date - * @param mixed number of days for adjustment - * @param array of mixed Optional Date Series - * @return long Interval between the dates - */ - public static function WORKDAY($startDate,$endDays) { - // Retrieve the mandatory start date and days that are referenced in the function definition - $startDate = self::flattenSingleValue($startDate); - $endDays = (int) self::flattenSingleValue($endDays); - // Flush the mandatory start date and days that are referenced in the function definition, and get the optional days - $dateArgs = self::flattenArray(func_get_args()); - array_shift($dateArgs); - array_shift($dateArgs); - - if ((is_string($startDate = self::_getDateValue($startDate))) || (!is_numeric($endDays))) { - return self::$_errorCodes['value']; - } - $startDate = (float) floor($startDate); - // If endDays is 0, we always return startDate - if ($endDays == 0) { return $startDate; } - - $decrementing = ($endDays < 0) ? True : False; - - // Adjust the start date if it falls over a weekend - - $startDoW = self::DAYOFWEEK($startDate,3); - if (self::DAYOFWEEK($startDate,3) >= 5) { - $startDate += ($decrementing) ? -$startDoW + 4: 7 - $startDoW; - ($decrementing) ? $endDays++ : $endDays--; - } - - // Add endDays - $endDate = (float) $startDate + (intval($endDays / 5) * 7) + ($endDays % 5); - - // Adjust the calculated end date if it falls over a weekend - $endDoW = self::DAYOFWEEK($endDate,3); - if ($endDoW >= 5) { - $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; - } - - // Test any extra holiday parameters - if (count($dateArgs) > 0) { - $holidayCountedArray = $holidayDates = array(); - foreach ($dateArgs as $holidayDate) { - if ((!is_null($holidayDate)) && (trim($holidayDate) > '')) { - if (is_string($holidayDate = self::_getDateValue($holidayDate))) { - return self::$_errorCodes['value']; - } - if (self::DAYOFWEEK($holidayDate,3) < 5) { - $holidayDates[] = $holidayDate; - } - } - } - if ($decrementing) { - rsort($holidayDates, SORT_NUMERIC); - } else { - sort($holidayDates, SORT_NUMERIC); - } - foreach ($holidayDates as $holidayDate) { - if ($decrementing) { - if (($holidayDate <= $startDate) && ($holidayDate >= $endDate)) { - if (!in_array($holidayDate,$holidayCountedArray)) { - --$endDate; - $holidayCountedArray[] = $holidayDate; - } - } - } else { - if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { - if (!in_array($holidayDate,$holidayCountedArray)) { - ++$endDate; - $holidayCountedArray[] = $holidayDate; - } - } - } - // Adjust the calculated end date if it falls over a weekend - $endDoW = self::DAYOFWEEK($endDate,3); - if ($endDoW >= 5) { - $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; - } - - } - } - - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) $endDate; - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP($endDate); - break; - case self::RETURNDATE_PHP_OBJECT : return PHPExcel_Shared_Date::ExcelToPHPObject($endDate); - break; - } - } // function WORKDAY() - - - /** - * DAYOFMONTH - * - * @param long $dateValue Excel date serial value or a standard date string - * @return int Day - */ - public static function DAYOFMONTH($dateValue = 1) { - $dateValue = self::flattenSingleValue($dateValue); - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } elseif ($dateValue == 0.0) { - return 0; - } elseif ($dateValue < 0.0) { - return self::$_errorCodes['num']; - } - - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - - return (int) $PHPDateObject->format('j'); - } // function DAYOFMONTH() - - - /** - * DAYOFWEEK - * - * @param long $dateValue Excel date serial value or a standard date string - * @return int Day - */ - public static function DAYOFWEEK($dateValue = 1, $style = 1) { - $dateValue = self::flattenSingleValue($dateValue); - $style = floor(self::flattenSingleValue($style)); - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } elseif ($dateValue < 0.0) { - return self::$_errorCodes['num']; - } - - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - $DoW = $PHPDateObject->format('w'); - - $firstDay = 1; - switch ($style) { - case 1: ++$DoW; - break; - case 2: if ($DoW == 0) { $DoW = 7; } - break; - case 3: if ($DoW == 0) { $DoW = 7; } - $firstDay = 0; - --$DoW; - break; - default: - } - if (self::$compatibilityMode == self::COMPATIBILITY_EXCEL) { - // Test for Excel's 1900 leap year, and introduce the error as required - if (($PHPDateObject->format('Y') == 1900) && ($PHPDateObject->format('n') <= 2)) { - --$DoW; - if ($DoW < $firstDay) { - $DoW += 7; - } - } - } - - return (int) $DoW; - } // function DAYOFWEEK() - - - /** - * WEEKOFYEAR - * - * @param long $dateValue Excel date serial value or a standard date string - * @param boolean $method Week begins on Sunday or Monday - * @return int Week Number - */ - public static function WEEKOFYEAR($dateValue = 1, $method = 1) { - $dateValue = self::flattenSingleValue($dateValue); - $method = floor(self::flattenSingleValue($method)); - - if (!is_numeric($method)) { - return self::$_errorCodes['value']; - } elseif (($method < 1) || ($method > 2)) { - return self::$_errorCodes['num']; - } - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } elseif ($dateValue < 0.0) { - return self::$_errorCodes['num']; - } - - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - $dayOfYear = $PHPDateObject->format('z'); - $dow = $PHPDateObject->format('w'); - $PHPDateObject->modify('-'.$dayOfYear.' days'); - $dow = $PHPDateObject->format('w'); - $daysInFirstWeek = 7 - (($dow + (2 - $method)) % 7); - $dayOfYear -= $daysInFirstWeek; - $weekOfYear = ceil($dayOfYear / 7) + 1; - - return (int) $weekOfYear; - } // function WEEKOFYEAR() - - - /** - * MONTHOFYEAR - * - * @param long $dateValue Excel date serial value or a standard date string - * @return int Month - */ - public static function MONTHOFYEAR($dateValue = 1) { - $dateValue = self::flattenSingleValue($dateValue); - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } elseif ($dateValue < 0.0) { - return self::$_errorCodes['num']; - } - - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - - return (int) $PHPDateObject->format('n'); - } // function MONTHOFYEAR() - - - /** - * YEAR - * - * @param long $dateValue Excel date serial value or a standard date string - * @return int Year - */ - public static function YEAR($dateValue = 1) { - $dateValue = self::flattenSingleValue($dateValue); - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } elseif ($dateValue < 0.0) { - return self::$_errorCodes['num']; - } - - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - - return (int) $PHPDateObject->format('Y'); - } // function YEAR() - - - /** - * HOUROFDAY - * - * @param mixed $timeValue Excel time serial value or a standard time string - * @return int Hour - */ - public static function HOUROFDAY($timeValue = 0) { - $timeValue = self::flattenSingleValue($timeValue); - - if (!is_numeric($timeValue)) { - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $testVal = strtok($timeValue,'/-: '); - if (strlen($testVal) < strlen($timeValue)) { - return self::$_errorCodes['value']; - } - } - $timeValue = self::_getTimeValue($timeValue); - if (is_string($timeValue)) { - return self::$_errorCodes['value']; - } - } - // Execute function - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); - - return (int) gmdate('G',$timeValue); - } // function HOUROFDAY() - - - /** - * MINUTEOFHOUR - * - * @param long $timeValue Excel time serial value or a standard time string - * @return int Minute - */ - public static function MINUTEOFHOUR($timeValue = 0) { - $timeValue = $timeTester = self::flattenSingleValue($timeValue); - - if (!is_numeric($timeValue)) { - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $testVal = strtok($timeValue,'/-: '); - if (strlen($testVal) < strlen($timeValue)) { - return self::$_errorCodes['value']; - } - } - $timeValue = self::_getTimeValue($timeValue); - if (is_string($timeValue)) { - return self::$_errorCodes['value']; - } - } - // Execute function - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); - - return (int) gmdate('i',$timeValue); - } // function MINUTEOFHOUR() - - - /** - * SECONDOFMINUTE - * - * @param long $timeValue Excel time serial value or a standard time string - * @return int Second - */ - public static function SECONDOFMINUTE($timeValue = 0) { - $timeValue = self::flattenSingleValue($timeValue); - - if (!is_numeric($timeValue)) { - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $testVal = strtok($timeValue,'/-: '); - if (strlen($testVal) < strlen($timeValue)) { - return self::$_errorCodes['value']; - } - } - $timeValue = self::_getTimeValue($timeValue); - if (is_string($timeValue)) { - return self::$_errorCodes['value']; - } - } - // Execute function - if ($timeValue >= 1) { - $timeValue = fmod($timeValue,1); - } elseif ($timeValue < 0.0) { - return self::$_errorCodes['num']; - } - $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); - - return (int) gmdate('s',$timeValue); - } // function SECONDOFMINUTE() - - - private static function _adjustDateByMonths($dateValue = 0, $adjustmentMonths = 0) { - // Execute function - $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); - $oMonth = (int) $PHPDateObject->format('m'); - $oYear = (int) $PHPDateObject->format('Y'); - - $adjustmentMonthsString = (string) $adjustmentMonths; - if ($adjustmentMonths > 0) { - $adjustmentMonthsString = '+'.$adjustmentMonths; - } - if ($adjustmentMonths != 0) { - $PHPDateObject->modify($adjustmentMonthsString.' months'); - } - $nMonth = (int) $PHPDateObject->format('m'); - $nYear = (int) $PHPDateObject->format('Y'); - - $monthDiff = ($nMonth - $oMonth) + (($nYear - $oYear) * 12); - if ($monthDiff != $adjustmentMonths) { - $adjustDays = (int) $PHPDateObject->format('d'); - $adjustDaysString = '-'.$adjustDays.' days'; - $PHPDateObject->modify($adjustDaysString); - } - return $PHPDateObject; - } // function _adjustDateByMonths() - - - /** - * EDATE - * - * Returns the serial number that represents the date that is the indicated number of months before or after a specified date - * (the start_date). Use EDATE to calculate maturity dates or due dates that fall on the same day of the month as the date of issue. - * - * @param long $dateValue Excel date serial value or a standard date string - * @param int $adjustmentMonths Number of months to adjust by - * @return long Excel date serial value - */ - public static function EDATE($dateValue = 1, $adjustmentMonths = 0) { - $dateValue = self::flattenSingleValue($dateValue); - $adjustmentMonths = floor(self::flattenSingleValue($adjustmentMonths)); - - if (!is_numeric($adjustmentMonths)) { - return self::$_errorCodes['value']; - } - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } - - // Execute function - $PHPDateObject = self::_adjustDateByMonths($dateValue,$adjustmentMonths); - - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) PHPExcel_Shared_Date::PHPToExcel($PHPDateObject); - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::PHPToExcel($PHPDateObject)); - break; - case self::RETURNDATE_PHP_OBJECT : return $PHPDateObject; - break; - } - } // function EDATE() - - - /** - * EOMONTH - * - * Returns the serial number for the last day of the month that is the indicated number of months before or after start_date. - * Use EOMONTH to calculate maturity dates or due dates that fall on the last day of the month. - * - * @param long $dateValue Excel date serial value or a standard date string - * @param int $adjustmentMonths Number of months to adjust by - * @return long Excel date serial value - */ - public static function EOMONTH($dateValue = 1, $adjustmentMonths = 0) { - $dateValue = self::flattenSingleValue($dateValue); - $adjustmentMonths = floor(self::flattenSingleValue($adjustmentMonths)); - - if (!is_numeric($adjustmentMonths)) { - return self::$_errorCodes['value']; - } - - if (is_string($dateValue = self::_getDateValue($dateValue))) { - return self::$_errorCodes['value']; - } - - // Execute function - $PHPDateObject = self::_adjustDateByMonths($dateValue,$adjustmentMonths+1); - $adjustDays = (int) $PHPDateObject->format('d'); - $adjustDaysString = '-'.$adjustDays.' days'; - $PHPDateObject->modify($adjustDaysString); - - switch (self::getReturnDateType()) { - case self::RETURNDATE_EXCEL : return (float) PHPExcel_Shared_Date::PHPToExcel($PHPDateObject); - break; - case self::RETURNDATE_PHP_NUMERIC : return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::PHPToExcel($PHPDateObject)); - break; - case self::RETURNDATE_PHP_OBJECT : return $PHPDateObject; - break; - } - } // function EOMONTH() - - - /** - * TRUNC - * - * Truncates value to the number of fractional digits by number_digits. - * - * @param float $value - * @param int $number_digits - * @return float Truncated value - */ - public static function TRUNC($value = 0, $number_digits = 0) { - $value = self::flattenSingleValue($value); - $number_digits = self::flattenSingleValue($number_digits); - - // Validate parameters - if ($number_digits < 0) { - return self::$_errorCodes['value']; - } - - // Truncate - if ($number_digits > 0) { - $value = $value * pow(10, $number_digits); - } - $value = intval($value); - if ($number_digits > 0) { - $value = $value / pow(10, $number_digits); - } - - // Return - return $value; - } // function TRUNC() - - /** - * POWER - * - * Computes x raised to the power y. - * - * @param float $x - * @param float $y - * @return float - */ - public static function POWER($x = 0, $y = 2) { - $x = self::flattenSingleValue($x); - $y = self::flattenSingleValue($y); - - // Validate parameters - if ($x == 0 && $y <= 0) { - return self::$_errorCodes['divisionbyzero']; - } - - // Return - return pow($x, $y); - } // function POWER() - - - private static function _nbrConversionFormat($xVal,$places) { - if (!is_null($places)) { - if (strlen($xVal) <= $places) { - return substr(str_pad($xVal,$places,'0',STR_PAD_LEFT),-10); - } else { - return self::$_errorCodes['num']; - } - } - - return substr($xVal,-10); - } // function _nbrConversionFormat() - - - /** - * BINTODEC - * - * Return a binary value as Decimal. - * - * @param string $x - * @return string - */ - public static function BINTODEC($x) { - $x = self::flattenSingleValue($x); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $x = floor($x); - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { - return self::$_errorCodes['num']; - } - if (strlen($x) > 10) { - return self::$_errorCodes['num']; - } elseif (strlen($x) == 10) { - // Two's Complement - $x = substr($x,-9); - return '-'.(512-bindec($x)); - } - return bindec($x); - } // function BINTODEC() - - - /** - * BINTOHEX - * - * Return a binary value as Hex. - * - * @param string $x - * @return string - */ - public static function BINTOHEX($x, $places=null) { - $x = floor(self::flattenSingleValue($x)); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $x = floor($x); - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { - return self::$_errorCodes['num']; - } - if (strlen($x) > 10) { - return self::$_errorCodes['num']; - } elseif (strlen($x) == 10) { - // Two's Complement - return str_repeat('F',8).substr(strtoupper(dechex(bindec(substr($x,-9)))),-2); - } - $hexVal = (string) strtoupper(dechex(bindec($x))); - - return self::_nbrConversionFormat($hexVal,$places); - } // function BINTOHEX() - - - /** - * BINTOOCT - * - * Return a binary value as Octal. - * - * @param string $x - * @return string - */ - public static function BINTOOCT($x, $places=null) { - $x = floor(self::flattenSingleValue($x)); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $x = floor($x); - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { - return self::$_errorCodes['num']; - } - if (strlen($x) > 10) { - return self::$_errorCodes['num']; - } elseif (strlen($x) == 10) { - // Two's Complement - return str_repeat('7',7).substr(strtoupper(decoct(bindec(substr($x,-9)))),-3); - } - $octVal = (string) decoct(bindec($x)); - - return self::_nbrConversionFormat($octVal,$places); - } // function BINTOOCT() - - - /** - * DECTOBIN - * - * Return an octal value as binary. - * - * @param string $x - * @return string - */ - public static function DECTOBIN($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { - return self::$_errorCodes['value']; - } - $x = (string) floor($x); - $r = decbin($x); - if (strlen($r) == 32) { - // Two's Complement - $r = substr($r,-10); - } elseif (strlen($r) > 11) { - return self::$_errorCodes['num']; - } - - return self::_nbrConversionFormat($r,$places); - } // function DECTOBIN() - - - /** - * DECTOOCT - * - * Return an octal value as binary. - * - * @param string $x - * @return string - */ - public static function DECTOOCT($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { - return self::$_errorCodes['value']; - } - $x = (string) floor($x); - $r = decoct($x); - if (strlen($r) == 11) { - // Two's Complement - $r = substr($r,-10); - } - - return self::_nbrConversionFormat($r,$places); - } // function DECTOOCT() - - - /** - * DECTOHEX - * - * Return an octal value as binary. - * - * @param string $x - * @return string - */ - public static function DECTOHEX($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - $x = (int) $x; - } else { - return self::$_errorCodes['value']; - } - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { - return self::$_errorCodes['value']; - } - $x = (string) floor($x); - $r = strtoupper(dechex($x)); - if (strlen($r) == 8) { - // Two's Complement - $r = 'FF'.$r; - } - - return self::_nbrConversionFormat($r,$places); - } // function DECTOHEX() - - - /** - * HEXTOBIN - * - * Return a hex value as binary. - * - * @param string $x - * @return string - */ - public static function HEXTOBIN($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { - return self::$_errorCodes['num']; - } - $binVal = decbin(hexdec($x)); - - return substr(self::_nbrConversionFormat($binVal,$places),-10); - } // function HEXTOBIN() - - - /** - * HEXTOOCT - * - * Return a hex value as octal. - * - * @param string $x - * @return string - */ - public static function HEXTOOCT($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { - return self::$_errorCodes['num']; - } - $octVal = decoct(hexdec($x)); - - return self::_nbrConversionFormat($octVal,$places); - } // function HEXTOOCT() - - - /** - * HEXTODEC - * - * Return a hex value as octal. - * - * @param string $x - * @return string - */ - public static function HEXTODEC($x) { - $x = self::flattenSingleValue($x); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { - return self::$_errorCodes['num']; - } - return hexdec($x); - } // function HEXTODEC() - - - /** - * OCTTOBIN - * - * Return an octal value as binary. - * - * @param string $x - * @return string - */ - public static function OCTTOBIN($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { - return self::$_errorCodes['num']; - } - $r = decbin(octdec($x)); - - return self::_nbrConversionFormat($r,$places); - } // function OCTTOBIN() - - - /** - * OCTTODEC - * - * Return an octal value as binary. - * - * @param string $x - * @return string - */ - public static function OCTTODEC($x) { - $x = self::flattenSingleValue($x); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { - return self::$_errorCodes['num']; - } - return octdec($x); - } // function OCTTODEC() - - - /** - * OCTTOHEX - * - * Return an octal value as hex. - * - * @param string $x - * @return string - */ - public static function OCTTOHEX($x, $places=null) { - $x = self::flattenSingleValue($x); - $places = self::flattenSingleValue($places); - - if (is_bool($x)) { - return self::$_errorCodes['value']; - } - $x = (string) $x; - if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { - return self::$_errorCodes['num']; - } - $hexVal = strtoupper(dechex(octdec($x))); - - return self::_nbrConversionFormat($hexVal,$places); - } // function OCTTOHEX() - - - public static function _parseComplex($complexNumber) { - $workString = (string) $complexNumber; - - $realNumber = $imaginary = 0; - // Extract the suffix, if there is one - $suffix = substr($workString,-1); - if (!is_numeric($suffix)) { - $workString = substr($workString,0,-1); - } else { - $suffix = ''; - } - - // Split the input into its Real and Imaginary components - $leadingSign = 0; - if (strlen($workString) > 0) { - $leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0; - } - $power = ''; - $realNumber = strtok($workString, '+-'); - if (strtoupper(substr($realNumber,-1)) == 'E') { - $power = strtok('+-'); - ++$leadingSign; - } - - $realNumber = substr($workString,0,strlen($realNumber)+strlen($power)+$leadingSign); - - if ($suffix != '') { - $imaginary = substr($workString,strlen($realNumber)); - - if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) { - $imaginary = $realNumber.'1'; - $realNumber = '0'; - } else if ($imaginary == '') { - $imaginary = $realNumber; - $realNumber = '0'; - } elseif (($imaginary == '+') || ($imaginary == '-')) { - $imaginary .= '1'; - } - } - - $complexArray = array( 'real' => $realNumber, - 'imaginary' => $imaginary, - 'suffix' => $suffix - ); - - return $complexArray; - } // function _parseComplex() - - - private static function _cleanComplex($complexNumber) { - if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1); - if ($complexNumber{0} == '0') $complexNumber = substr($complexNumber,1); - if ($complexNumber{0} == '.') $complexNumber = '0'.$complexNumber; - if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1); - return $complexNumber; - } - - - /** - * COMPLEX - * - * returns a complex number of the form x + yi or x + yj. - * - * @param float $realNumber - * @param float $imaginary - * @param string $suffix - * @return string - */ - public static function COMPLEX($realNumber=0.0, $imaginary=0.0, $suffix='i') { - $realNumber = (is_null($realNumber)) ? 0.0 : (float) self::flattenSingleValue($realNumber); - $imaginary = (is_null($imaginary)) ? 0.0 : (float) self::flattenSingleValue($imaginary); - $suffix = (is_null($suffix)) ? 'i' : self::flattenSingleValue($suffix); - - if (((is_numeric($realNumber)) && (is_numeric($imaginary))) && - (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))) { - if ($suffix == '') $suffix = 'i'; - if ($realNumber == 0.0) { - if ($imaginary == 0.0) { - return (string) '0'; - } elseif ($imaginary == 1.0) { - return (string) $suffix; - } elseif ($imaginary == -1.0) { - return (string) '-'.$suffix; - } - return (string) $imaginary.$suffix; - } elseif ($imaginary == 0.0) { - return (string) $realNumber; - } elseif ($imaginary == 1.0) { - return (string) $realNumber.'+'.$suffix; - } elseif ($imaginary == -1.0) { - return (string) $realNumber.'-'.$suffix; - } - if ($imaginary > 0) { $imaginary = (string) '+'.$imaginary; } - return (string) $realNumber.$imaginary.$suffix; - } - return self::$_errorCodes['value']; - } // function COMPLEX() - - - /** - * IMAGINARY - * - * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return real - */ - public static function IMAGINARY($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - return $parsedComplex['imaginary']; - } // function IMAGINARY() - - - /** - * IMREAL - * - * Returns the real coefficient of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return real - */ - public static function IMREAL($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - return $parsedComplex['real']; - } // function IMREAL() - - - /** - * IMABS - * - * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return real - */ - public static function IMABS($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - return sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])); - } // function IMABS() - - - /** - * IMARGUMENT - * - * Returns the argument theta of a complex number, i.e. the angle in radians from the real axis to the representation of the number in polar coordinates. - * - * @param string $complexNumber - * @return string - */ - public static function IMARGUMENT($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if ($parsedComplex['real'] == 0.0) { - if ($parsedComplex['imaginary'] == 0.0) { - return 0.0; - } elseif($parsedComplex['imaginary'] < 0.0) { - return M_PI / -2; - } else { - return M_PI / 2; - } - } elseif ($parsedComplex['real'] > 0.0) { - return atan($parsedComplex['imaginary'] / $parsedComplex['real']); - } elseif ($parsedComplex['imaginary'] < 0.0) { - return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); - } else { - return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); - } - } // function IMARGUMENT() - - - /** - * IMCONJUGATE - * - * Returns the complex conjugate of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMCONJUGATE($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if ($parsedComplex['imaginary'] == 0.0) { - return $parsedComplex['real']; - } else { - return self::_cleanComplex(self::COMPLEX($parsedComplex['real'], 0 - $parsedComplex['imaginary'], $parsedComplex['suffix'])); - } - } // function IMCONJUGATE() - - - /** - * IMCOS - * - * Returns the cosine of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMCOS($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if ($parsedComplex['imaginary'] == 0.0) { - return cos($parsedComplex['real']); - } else { - return self::IMCONJUGATE(self::COMPLEX(cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix'])); - } - } // function IMCOS() - - - /** - * IMSIN - * - * Returns the sine of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMSIN($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if ($parsedComplex['imaginary'] == 0.0) { - return sin($parsedComplex['real']); - } else { - return self::COMPLEX(sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix']); - } - } // function IMSIN() - - - /** - * IMSQRT - * - * Returns the square root of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMSQRT($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - $theta = self::IMARGUMENT($complexNumber); - $d1 = cos($theta / 2); - $d2 = sin($theta / 2); - $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']))); - - if ($parsedComplex['suffix'] == '') { - return self::COMPLEX($d1 * $r,$d2 * $r); - } else { - return self::COMPLEX($d1 * $r,$d2 * $r,$parsedComplex['suffix']); - } - } // function IMSQRT() - - - /** - * IMLN - * - * Returns the natural logarithm of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMLN($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return self::$_errorCodes['num']; - } - - $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']))); - $t = self::IMARGUMENT($complexNumber); - - if ($parsedComplex['suffix'] == '') { - return self::COMPLEX($logR,$t); - } else { - return self::COMPLEX($logR,$t,$parsedComplex['suffix']); - } - } // function IMLN() - - - /** - * IMLOG10 - * - * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMLOG10($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return self::$_errorCodes['num']; - } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return log10($parsedComplex['real']); - } - - return self::IMPRODUCT(log10(EULER),self::IMLN($complexNumber)); - } // function IMLOG10() - - - /** - * IMLOG2 - * - * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMLOG2($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return self::$_errorCodes['num']; - } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return log($parsedComplex['real'],2); - } - - return self::IMPRODUCT(log(EULER,2),self::IMLN($complexNumber)); - } // function IMLOG2() - - - /** - * IMEXP - * - * Returns the exponential of a complex number in x + yi or x + yj text format. - * - * @param string $complexNumber - * @return string - */ - public static function IMEXP($complexNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { - return '1'; - } - - $e = exp($parsedComplex['real']); - $eX = $e * cos($parsedComplex['imaginary']); - $eY = $e * sin($parsedComplex['imaginary']); - - if ($parsedComplex['suffix'] == '') { - return self::COMPLEX($eX,$eY); - } else { - return self::COMPLEX($eX,$eY,$parsedComplex['suffix']); - } - } // function IMEXP() - - - /** - * IMPOWER - * - * Returns a complex number in x + yi or x + yj text format raised to a power. - * - * @param string $complexNumber - * @return string - */ - public static function IMPOWER($complexNumber,$realNumber) { - $complexNumber = self::flattenSingleValue($complexNumber); - $realNumber = self::flattenSingleValue($realNumber); - - if (!is_numeric($realNumber)) { - return self::$_errorCodes['value']; - } - - $parsedComplex = self::_parseComplex($complexNumber); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])); - $rPower = pow($r,$realNumber); - $theta = self::IMARGUMENT($complexNumber) * $realNumber; - if ($theta == 0) { - return 1; - } elseif ($parsedComplex['imaginary'] == 0.0) { - return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']); - } else { - return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']); - } - } // function IMPOWER() - - - /** - * IMDIV - * - * Returns the quotient of two complex numbers in x + yi or x + yj text format. - * - * @param string $complexDividend - * @param string $complexDivisor - * @return real - */ - public static function IMDIV($complexDividend,$complexDivisor) { - $complexDividend = self::flattenSingleValue($complexDividend); - $complexDivisor = self::flattenSingleValue($complexDivisor); - - $parsedComplexDividend = self::_parseComplex($complexDividend); - if (!is_array($parsedComplexDividend)) { - return $parsedComplexDividend; - } - - $parsedComplexDivisor = self::_parseComplex($complexDivisor); - if (!is_array($parsedComplexDivisor)) { - return $parsedComplexDividend; - } - - if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') && - ($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])) { - return self::$_errorCodes['num']; - } - if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) { - $parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix']; - } - - $d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']); - $d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']); - $d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']); - - $r = $d1/$d3; - $i = $d2/$d3; - - if ($i > 0.0) { - return self::_cleanComplex($r.'+'.$i.$parsedComplexDivisor['suffix']); - } elseif ($i < 0.0) { - return self::_cleanComplex($r.$i.$parsedComplexDivisor['suffix']); - } else { - return $r; - } - } // function IMDIV() - - - /** - * IMSUB - * - * Returns the difference of two complex numbers in x + yi or x + yj text format. - * - * @param string $complexNumber1 - * @param string $complexNumber2 - * @return real - */ - public static function IMSUB($complexNumber1,$complexNumber2) { - $complexNumber1 = self::flattenSingleValue($complexNumber1); - $complexNumber2 = self::flattenSingleValue($complexNumber2); - - $parsedComplex1 = self::_parseComplex($complexNumber1); - if (!is_array($parsedComplex1)) { - return $parsedComplex1; - } - - $parsedComplex2 = self::_parseComplex($complexNumber2); - if (!is_array($parsedComplex2)) { - return $parsedComplex2; - } - - if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) && - ($parsedComplex1['suffix'] != $parsedComplex2['suffix'])) { - return self::$_errorCodes['num']; - } elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) { - $parsedComplex1['suffix'] = $parsedComplex2['suffix']; - } - - $d1 = $parsedComplex1['real'] - $parsedComplex2['real']; - $d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary']; - - return self::COMPLEX($d1,$d2,$parsedComplex1['suffix']); - } // function IMSUB() - - - /** - * IMSUM - * - * Returns the sum of two or more complex numbers in x + yi or x + yj text format. - * - * @param array of mixed Data Series - * @return real - */ - public static function IMSUM() { - // Return value - $returnValue = self::_parseComplex('0'); - $activeSuffix = ''; - - // Loop through the arguments - $aArgs = self::flattenArray(func_get_args()); - foreach ($aArgs as $arg) { - $parsedComplex = self::_parseComplex($arg); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - - if ($activeSuffix == '') { - $activeSuffix = $parsedComplex['suffix']; - } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) { - return self::$_errorCodes['value']; - } - - $returnValue['real'] += $parsedComplex['real']; - $returnValue['imaginary'] += $parsedComplex['imaginary']; - } - - if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; } - return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix); - } // function IMSUM() - - - /** - * IMPRODUCT - * - * Returns the product of two or more complex numbers in x + yi or x + yj text format. - * - * @param array of mixed Data Series - * @return real - */ - public static function IMPRODUCT() { - // Return value - $returnValue = self::_parseComplex('1'); - $activeSuffix = ''; - - // Loop through the arguments - $aArgs = self::flattenArray(func_get_args()); - foreach ($aArgs as $arg) { - $parsedComplex = self::_parseComplex($arg); - if (!is_array($parsedComplex)) { - return $parsedComplex; - } - $workValue = $returnValue; - if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) { - $activeSuffix = $parsedComplex['suffix']; - } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) { - return self::$_errorCodes['num']; - } - $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']); - $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']); - } - - if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; } - return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix); - } // function IMPRODUCT() - - - private static $_conversionUnits = array( 'g' => array( 'Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => True ), - 'sg' => array( 'Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => False ), - 'lbm' => array( 'Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => False ), - 'u' => array( 'Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => True ), - 'ozm' => array( 'Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => False ), - 'm' => array( 'Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => True ), - 'mi' => array( 'Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => False ), - 'Nmi' => array( 'Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => False ), - 'in' => array( 'Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => False ), - 'ft' => array( 'Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => False ), - 'yd' => array( 'Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => False ), - 'ang' => array( 'Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => True ), - 'Pica' => array( 'Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => False ), - 'yr' => array( 'Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => False ), - 'day' => array( 'Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => False ), - 'hr' => array( 'Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => False ), - 'mn' => array( 'Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => False ), - 'sec' => array( 'Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => True ), - 'Pa' => array( 'Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => True ), - 'p' => array( 'Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => True ), - 'atm' => array( 'Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => True ), - 'at' => array( 'Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => True ), - 'mmHg' => array( 'Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => True ), - 'N' => array( 'Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => True ), - 'dyn' => array( 'Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => True ), - 'dy' => array( 'Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => True ), - 'lbf' => array( 'Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => False ), - 'J' => array( 'Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => True ), - 'e' => array( 'Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => True ), - 'c' => array( 'Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => True ), - 'cal' => array( 'Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => True ), - 'eV' => array( 'Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => True ), - 'ev' => array( 'Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => True ), - 'HPh' => array( 'Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => False ), - 'hh' => array( 'Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => False ), - 'Wh' => array( 'Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => True ), - 'wh' => array( 'Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => True ), - 'flb' => array( 'Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => False ), - 'BTU' => array( 'Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => False ), - 'btu' => array( 'Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => False ), - 'HP' => array( 'Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => False ), - 'h' => array( 'Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => False ), - 'W' => array( 'Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => True ), - 'w' => array( 'Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => True ), - 'T' => array( 'Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => True ), - 'ga' => array( 'Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => True ), - 'C' => array( 'Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => False ), - 'cel' => array( 'Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => False ), - 'F' => array( 'Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => False ), - 'fah' => array( 'Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => False ), - 'K' => array( 'Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => False ), - 'kel' => array( 'Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => False ), - 'tsp' => array( 'Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => False ), - 'tbs' => array( 'Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => False ), - 'oz' => array( 'Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => False ), - 'cup' => array( 'Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => False ), - 'pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => False ), - 'us_pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => False ), - 'uk_pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => False ), - 'qt' => array( 'Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => False ), - 'gal' => array( 'Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => False ), - 'l' => array( 'Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => True ), - 'lt' => array( 'Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => True ) - ); - - private static $_conversionMultipliers = array( 'Y' => array( 'multiplier' => 1E24, 'name' => 'yotta' ), - 'Z' => array( 'multiplier' => 1E21, 'name' => 'zetta' ), - 'E' => array( 'multiplier' => 1E18, 'name' => 'exa' ), - 'P' => array( 'multiplier' => 1E15, 'name' => 'peta' ), - 'T' => array( 'multiplier' => 1E12, 'name' => 'tera' ), - 'G' => array( 'multiplier' => 1E9, 'name' => 'giga' ), - 'M' => array( 'multiplier' => 1E6, 'name' => 'mega' ), - 'k' => array( 'multiplier' => 1E3, 'name' => 'kilo' ), - 'h' => array( 'multiplier' => 1E2, 'name' => 'hecto' ), - 'e' => array( 'multiplier' => 1E1, 'name' => 'deka' ), - 'd' => array( 'multiplier' => 1E-1, 'name' => 'deci' ), - 'c' => array( 'multiplier' => 1E-2, 'name' => 'centi' ), - 'm' => array( 'multiplier' => 1E-3, 'name' => 'milli' ), - 'u' => array( 'multiplier' => 1E-6, 'name' => 'micro' ), - 'n' => array( 'multiplier' => 1E-9, 'name' => 'nano' ), - 'p' => array( 'multiplier' => 1E-12, 'name' => 'pico' ), - 'f' => array( 'multiplier' => 1E-15, 'name' => 'femto' ), - 'a' => array( 'multiplier' => 1E-18, 'name' => 'atto' ), - 'z' => array( 'multiplier' => 1E-21, 'name' => 'zepto' ), - 'y' => array( 'multiplier' => 1E-24, 'name' => 'yocto' ) - ); - - private static $_unitConversions = array( 'Mass' => array( 'g' => array( 'g' => 1.0, - 'sg' => 6.85220500053478E-05, - 'lbm' => 2.20462291469134E-03, - 'u' => 6.02217000000000E+23, - 'ozm' => 3.52739718003627E-02 - ), - 'sg' => array( 'g' => 1.45938424189287E+04, - 'sg' => 1.0, - 'lbm' => 3.21739194101647E+01, - 'u' => 8.78866000000000E+27, - 'ozm' => 5.14782785944229E+02 - ), - 'lbm' => array( 'g' => 4.5359230974881148E+02, - 'sg' => 3.10810749306493E-02, - 'lbm' => 1.0, - 'u' => 2.73161000000000E+26, - 'ozm' => 1.60000023429410E+01 - ), - 'u' => array( 'g' => 1.66053100460465E-24, - 'sg' => 1.13782988532950E-28, - 'lbm' => 3.66084470330684E-27, - 'u' => 1.0, - 'ozm' => 5.85735238300524E-26 - ), - 'ozm' => array( 'g' => 2.83495152079732E+01, - 'sg' => 1.94256689870811E-03, - 'lbm' => 6.24999908478882E-02, - 'u' => 1.70725600000000E+25, - 'ozm' => 1.0 - ) - ), - 'Distance' => array( 'm' => array( 'm' => 1.0, - 'mi' => 6.21371192237334E-04, - 'Nmi' => 5.39956803455724E-04, - 'in' => 3.93700787401575E+01, - 'ft' => 3.28083989501312E+00, - 'yd' => 1.09361329797891E+00, - 'ang' => 1.00000000000000E+10, - 'Pica' => 2.83464566929116E+03 - ), - 'mi' => array( 'm' => 1.60934400000000E+03, - 'mi' => 1.0, - 'Nmi' => 8.68976241900648E-01, - 'in' => 6.33600000000000E+04, - 'ft' => 5.28000000000000E+03, - 'yd' => 1.76000000000000E+03, - 'ang' => 1.60934400000000E+13, - 'Pica' => 4.56191999999971E+06 - ), - 'Nmi' => array( 'm' => 1.85200000000000E+03, - 'mi' => 1.15077944802354E+00, - 'Nmi' => 1.0, - 'in' => 7.29133858267717E+04, - 'ft' => 6.07611548556430E+03, - 'yd' => 2.02537182785694E+03, - 'ang' => 1.85200000000000E+13, - 'Pica' => 5.24976377952723E+06 - ), - 'in' => array( 'm' => 2.54000000000000E-02, - 'mi' => 1.57828282828283E-05, - 'Nmi' => 1.37149028077754E-05, - 'in' => 1.0, - 'ft' => 8.33333333333333E-02, - 'yd' => 2.77777777686643E-02, - 'ang' => 2.54000000000000E+08, - 'Pica' => 7.19999999999955E+01 - ), - 'ft' => array( 'm' => 3.04800000000000E-01, - 'mi' => 1.89393939393939E-04, - 'Nmi' => 1.64578833693305E-04, - 'in' => 1.20000000000000E+01, - 'ft' => 1.0, - 'yd' => 3.33333333223972E-01, - 'ang' => 3.04800000000000E+09, - 'Pica' => 8.63999999999946E+02 - ), - 'yd' => array( 'm' => 9.14400000300000E-01, - 'mi' => 5.68181818368230E-04, - 'Nmi' => 4.93736501241901E-04, - 'in' => 3.60000000118110E+01, - 'ft' => 3.00000000000000E+00, - 'yd' => 1.0, - 'ang' => 9.14400000300000E+09, - 'Pica' => 2.59200000085023E+03 - ), - 'ang' => array( 'm' => 1.00000000000000E-10, - 'mi' => 6.21371192237334E-14, - 'Nmi' => 5.39956803455724E-14, - 'in' => 3.93700787401575E-09, - 'ft' => 3.28083989501312E-10, - 'yd' => 1.09361329797891E-10, - 'ang' => 1.0, - 'Pica' => 2.83464566929116E-07 - ), - 'Pica' => array( 'm' => 3.52777777777800E-04, - 'mi' => 2.19205948372629E-07, - 'Nmi' => 1.90484761219114E-07, - 'in' => 1.38888888888898E-02, - 'ft' => 1.15740740740748E-03, - 'yd' => 3.85802469009251E-04, - 'ang' => 3.52777777777800E+06, - 'Pica' => 1.0 - ) - ), - 'Time' => array( 'yr' => array( 'yr' => 1.0, - 'day' => 365.25, - 'hr' => 8766.0, - 'mn' => 525960.0, - 'sec' => 31557600.0 - ), - 'day' => array( 'yr' => 2.73785078713210E-03, - 'day' => 1.0, - 'hr' => 24.0, - 'mn' => 1440.0, - 'sec' => 86400.0 - ), - 'hr' => array( 'yr' => 1.14077116130504E-04, - 'day' => 4.16666666666667E-02, - 'hr' => 1.0, - 'mn' => 60.0, - 'sec' => 3600.0 - ), - 'mn' => array( 'yr' => 1.90128526884174E-06, - 'day' => 6.94444444444444E-04, - 'hr' => 1.66666666666667E-02, - 'mn' => 1.0, - 'sec' => 60.0 - ), - 'sec' => array( 'yr' => 3.16880878140289E-08, - 'day' => 1.15740740740741E-05, - 'hr' => 2.77777777777778E-04, - 'mn' => 1.66666666666667E-02, - 'sec' => 1.0 - ) - ), - 'Pressure' => array( 'Pa' => array( 'Pa' => 1.0, - 'p' => 1.0, - 'atm' => 9.86923299998193E-06, - 'at' => 9.86923299998193E-06, - 'mmHg' => 7.50061707998627E-03 - ), - 'p' => array( 'Pa' => 1.0, - 'p' => 1.0, - 'atm' => 9.86923299998193E-06, - 'at' => 9.86923299998193E-06, - 'mmHg' => 7.50061707998627E-03 - ), - 'atm' => array( 'Pa' => 1.01324996583000E+05, - 'p' => 1.01324996583000E+05, - 'atm' => 1.0, - 'at' => 1.0, - 'mmHg' => 760.0 - ), - 'at' => array( 'Pa' => 1.01324996583000E+05, - 'p' => 1.01324996583000E+05, - 'atm' => 1.0, - 'at' => 1.0, - 'mmHg' => 760.0 - ), - 'mmHg' => array( 'Pa' => 1.33322363925000E+02, - 'p' => 1.33322363925000E+02, - 'atm' => 1.31578947368421E-03, - 'at' => 1.31578947368421E-03, - 'mmHg' => 1.0 - ) - ), - 'Force' => array( 'N' => array( 'N' => 1.0, - 'dyn' => 1.0E+5, - 'dy' => 1.0E+5, - 'lbf' => 2.24808923655339E-01 - ), - 'dyn' => array( 'N' => 1.0E-5, - 'dyn' => 1.0, - 'dy' => 1.0, - 'lbf' => 2.24808923655339E-06 - ), - 'dy' => array( 'N' => 1.0E-5, - 'dyn' => 1.0, - 'dy' => 1.0, - 'lbf' => 2.24808923655339E-06 - ), - 'lbf' => array( 'N' => 4.448222, - 'dyn' => 4.448222E+5, - 'dy' => 4.448222E+5, - 'lbf' => 1.0 - ) - ), - 'Energy' => array( 'J' => array( 'J' => 1.0, - 'e' => 9.99999519343231E+06, - 'c' => 2.39006249473467E-01, - 'cal' => 2.38846190642017E-01, - 'eV' => 6.24145700000000E+18, - 'ev' => 6.24145700000000E+18, - 'HPh' => 3.72506430801000E-07, - 'hh' => 3.72506430801000E-07, - 'Wh' => 2.77777916238711E-04, - 'wh' => 2.77777916238711E-04, - 'flb' => 2.37304222192651E+01, - 'BTU' => 9.47815067349015E-04, - 'btu' => 9.47815067349015E-04 - ), - 'e' => array( 'J' => 1.00000048065700E-07, - 'e' => 1.0, - 'c' => 2.39006364353494E-08, - 'cal' => 2.38846305445111E-08, - 'eV' => 6.24146000000000E+11, - 'ev' => 6.24146000000000E+11, - 'HPh' => 3.72506609848824E-14, - 'hh' => 3.72506609848824E-14, - 'Wh' => 2.77778049754611E-11, - 'wh' => 2.77778049754611E-11, - 'flb' => 2.37304336254586E-06, - 'BTU' => 9.47815522922962E-11, - 'btu' => 9.47815522922962E-11 - ), - 'c' => array( 'J' => 4.18399101363672E+00, - 'e' => 4.18398900257312E+07, - 'c' => 1.0, - 'cal' => 9.99330315287563E-01, - 'eV' => 2.61142000000000E+19, - 'ev' => 2.61142000000000E+19, - 'HPh' => 1.55856355899327E-06, - 'hh' => 1.55856355899327E-06, - 'Wh' => 1.16222030532950E-03, - 'wh' => 1.16222030532950E-03, - 'flb' => 9.92878733152102E+01, - 'BTU' => 3.96564972437776E-03, - 'btu' => 3.96564972437776E-03 - ), - 'cal' => array( 'J' => 4.18679484613929E+00, - 'e' => 4.18679283372801E+07, - 'c' => 1.00067013349059E+00, - 'cal' => 1.0, - 'eV' => 2.61317000000000E+19, - 'ev' => 2.61317000000000E+19, - 'HPh' => 1.55960800463137E-06, - 'hh' => 1.55960800463137E-06, - 'Wh' => 1.16299914807955E-03, - 'wh' => 1.16299914807955E-03, - 'flb' => 9.93544094443283E+01, - 'BTU' => 3.96830723907002E-03, - 'btu' => 3.96830723907002E-03 - ), - 'eV' => array( 'J' => 1.60219000146921E-19, - 'e' => 1.60218923136574E-12, - 'c' => 3.82933423195043E-20, - 'cal' => 3.82676978535648E-20, - 'eV' => 1.0, - 'ev' => 1.0, - 'HPh' => 5.96826078912344E-26, - 'hh' => 5.96826078912344E-26, - 'Wh' => 4.45053000026614E-23, - 'wh' => 4.45053000026614E-23, - 'flb' => 3.80206452103492E-18, - 'BTU' => 1.51857982414846E-22, - 'btu' => 1.51857982414846E-22 - ), - 'ev' => array( 'J' => 1.60219000146921E-19, - 'e' => 1.60218923136574E-12, - 'c' => 3.82933423195043E-20, - 'cal' => 3.82676978535648E-20, - 'eV' => 1.0, - 'ev' => 1.0, - 'HPh' => 5.96826078912344E-26, - 'hh' => 5.96826078912344E-26, - 'Wh' => 4.45053000026614E-23, - 'wh' => 4.45053000026614E-23, - 'flb' => 3.80206452103492E-18, - 'BTU' => 1.51857982414846E-22, - 'btu' => 1.51857982414846E-22 - ), - 'HPh' => array( 'J' => 2.68451741316170E+06, - 'e' => 2.68451612283024E+13, - 'c' => 6.41616438565991E+05, - 'cal' => 6.41186757845835E+05, - 'eV' => 1.67553000000000E+25, - 'ev' => 1.67553000000000E+25, - 'HPh' => 1.0, - 'hh' => 1.0, - 'Wh' => 7.45699653134593E+02, - 'wh' => 7.45699653134593E+02, - 'flb' => 6.37047316692964E+07, - 'BTU' => 2.54442605275546E+03, - 'btu' => 2.54442605275546E+03 - ), - 'hh' => array( 'J' => 2.68451741316170E+06, - 'e' => 2.68451612283024E+13, - 'c' => 6.41616438565991E+05, - 'cal' => 6.41186757845835E+05, - 'eV' => 1.67553000000000E+25, - 'ev' => 1.67553000000000E+25, - 'HPh' => 1.0, - 'hh' => 1.0, - 'Wh' => 7.45699653134593E+02, - 'wh' => 7.45699653134593E+02, - 'flb' => 6.37047316692964E+07, - 'BTU' => 2.54442605275546E+03, - 'btu' => 2.54442605275546E+03 - ), - 'Wh' => array( 'J' => 3.59999820554720E+03, - 'e' => 3.59999647518369E+10, - 'c' => 8.60422069219046E+02, - 'cal' => 8.59845857713046E+02, - 'eV' => 2.24692340000000E+22, - 'ev' => 2.24692340000000E+22, - 'HPh' => 1.34102248243839E-03, - 'hh' => 1.34102248243839E-03, - 'Wh' => 1.0, - 'wh' => 1.0, - 'flb' => 8.54294774062316E+04, - 'BTU' => 3.41213254164705E+00, - 'btu' => 3.41213254164705E+00 - ), - 'wh' => array( 'J' => 3.59999820554720E+03, - 'e' => 3.59999647518369E+10, - 'c' => 8.60422069219046E+02, - 'cal' => 8.59845857713046E+02, - 'eV' => 2.24692340000000E+22, - 'ev' => 2.24692340000000E+22, - 'HPh' => 1.34102248243839E-03, - 'hh' => 1.34102248243839E-03, - 'Wh' => 1.0, - 'wh' => 1.0, - 'flb' => 8.54294774062316E+04, - 'BTU' => 3.41213254164705E+00, - 'btu' => 3.41213254164705E+00 - ), - 'flb' => array( 'J' => 4.21400003236424E-02, - 'e' => 4.21399800687660E+05, - 'c' => 1.00717234301644E-02, - 'cal' => 1.00649785509554E-02, - 'eV' => 2.63015000000000E+17, - 'ev' => 2.63015000000000E+17, - 'HPh' => 1.56974211145130E-08, - 'hh' => 1.56974211145130E-08, - 'Wh' => 1.17055614802000E-05, - 'wh' => 1.17055614802000E-05, - 'flb' => 1.0, - 'BTU' => 3.99409272448406E-05, - 'btu' => 3.99409272448406E-05 - ), - 'BTU' => array( 'J' => 1.05505813786749E+03, - 'e' => 1.05505763074665E+10, - 'c' => 2.52165488508168E+02, - 'cal' => 2.51996617135510E+02, - 'eV' => 6.58510000000000E+21, - 'ev' => 6.58510000000000E+21, - 'HPh' => 3.93015941224568E-04, - 'hh' => 3.93015941224568E-04, - 'Wh' => 2.93071851047526E-01, - 'wh' => 2.93071851047526E-01, - 'flb' => 2.50369750774671E+04, - 'BTU' => 1.0, - 'btu' => 1.0, - ), - 'btu' => array( 'J' => 1.05505813786749E+03, - 'e' => 1.05505763074665E+10, - 'c' => 2.52165488508168E+02, - 'cal' => 2.51996617135510E+02, - 'eV' => 6.58510000000000E+21, - 'ev' => 6.58510000000000E+21, - 'HPh' => 3.93015941224568E-04, - 'hh' => 3.93015941224568E-04, - 'Wh' => 2.93071851047526E-01, - 'wh' => 2.93071851047526E-01, - 'flb' => 2.50369750774671E+04, - 'BTU' => 1.0, - 'btu' => 1.0, - ) - ), - 'Power' => array( 'HP' => array( 'HP' => 1.0, - 'h' => 1.0, - 'W' => 7.45701000000000E+02, - 'w' => 7.45701000000000E+02 - ), - 'h' => array( 'HP' => 1.0, - 'h' => 1.0, - 'W' => 7.45701000000000E+02, - 'w' => 7.45701000000000E+02 - ), - 'W' => array( 'HP' => 1.34102006031908E-03, - 'h' => 1.34102006031908E-03, - 'W' => 1.0, - 'w' => 1.0 - ), - 'w' => array( 'HP' => 1.34102006031908E-03, - 'h' => 1.34102006031908E-03, - 'W' => 1.0, - 'w' => 1.0 - ) - ), - 'Magnetism' => array( 'T' => array( 'T' => 1.0, - 'ga' => 10000.0 - ), - 'ga' => array( 'T' => 0.0001, - 'ga' => 1.0 - ) - ), - 'Liquid' => array( 'tsp' => array( 'tsp' => 1.0, - 'tbs' => 3.33333333333333E-01, - 'oz' => 1.66666666666667E-01, - 'cup' => 2.08333333333333E-02, - 'pt' => 1.04166666666667E-02, - 'us_pt' => 1.04166666666667E-02, - 'uk_pt' => 8.67558516821960E-03, - 'qt' => 5.20833333333333E-03, - 'gal' => 1.30208333333333E-03, - 'l' => 4.92999408400710E-03, - 'lt' => 4.92999408400710E-03 - ), - 'tbs' => array( 'tsp' => 3.00000000000000E+00, - 'tbs' => 1.0, - 'oz' => 5.00000000000000E-01, - 'cup' => 6.25000000000000E-02, - 'pt' => 3.12500000000000E-02, - 'us_pt' => 3.12500000000000E-02, - 'uk_pt' => 2.60267555046588E-02, - 'qt' => 1.56250000000000E-02, - 'gal' => 3.90625000000000E-03, - 'l' => 1.47899822520213E-02, - 'lt' => 1.47899822520213E-02 - ), - 'oz' => array( 'tsp' => 6.00000000000000E+00, - 'tbs' => 2.00000000000000E+00, - 'oz' => 1.0, - 'cup' => 1.25000000000000E-01, - 'pt' => 6.25000000000000E-02, - 'us_pt' => 6.25000000000000E-02, - 'uk_pt' => 5.20535110093176E-02, - 'qt' => 3.12500000000000E-02, - 'gal' => 7.81250000000000E-03, - 'l' => 2.95799645040426E-02, - 'lt' => 2.95799645040426E-02 - ), - 'cup' => array( 'tsp' => 4.80000000000000E+01, - 'tbs' => 1.60000000000000E+01, - 'oz' => 8.00000000000000E+00, - 'cup' => 1.0, - 'pt' => 5.00000000000000E-01, - 'us_pt' => 5.00000000000000E-01, - 'uk_pt' => 4.16428088074541E-01, - 'qt' => 2.50000000000000E-01, - 'gal' => 6.25000000000000E-02, - 'l' => 2.36639716032341E-01, - 'lt' => 2.36639716032341E-01 - ), - 'pt' => array( 'tsp' => 9.60000000000000E+01, - 'tbs' => 3.20000000000000E+01, - 'oz' => 1.60000000000000E+01, - 'cup' => 2.00000000000000E+00, - 'pt' => 1.0, - 'us_pt' => 1.0, - 'uk_pt' => 8.32856176149081E-01, - 'qt' => 5.00000000000000E-01, - 'gal' => 1.25000000000000E-01, - 'l' => 4.73279432064682E-01, - 'lt' => 4.73279432064682E-01 - ), - 'us_pt' => array( 'tsp' => 9.60000000000000E+01, - 'tbs' => 3.20000000000000E+01, - 'oz' => 1.60000000000000E+01, - 'cup' => 2.00000000000000E+00, - 'pt' => 1.0, - 'us_pt' => 1.0, - 'uk_pt' => 8.32856176149081E-01, - 'qt' => 5.00000000000000E-01, - 'gal' => 1.25000000000000E-01, - 'l' => 4.73279432064682E-01, - 'lt' => 4.73279432064682E-01 - ), - 'uk_pt' => array( 'tsp' => 1.15266000000000E+02, - 'tbs' => 3.84220000000000E+01, - 'oz' => 1.92110000000000E+01, - 'cup' => 2.40137500000000E+00, - 'pt' => 1.20068750000000E+00, - 'us_pt' => 1.20068750000000E+00, - 'uk_pt' => 1.0, - 'qt' => 6.00343750000000E-01, - 'gal' => 1.50085937500000E-01, - 'l' => 5.68260698087162E-01, - 'lt' => 5.68260698087162E-01 - ), - 'qt' => array( 'tsp' => 1.92000000000000E+02, - 'tbs' => 6.40000000000000E+01, - 'oz' => 3.20000000000000E+01, - 'cup' => 4.00000000000000E+00, - 'pt' => 2.00000000000000E+00, - 'us_pt' => 2.00000000000000E+00, - 'uk_pt' => 1.66571235229816E+00, - 'qt' => 1.0, - 'gal' => 2.50000000000000E-01, - 'l' => 9.46558864129363E-01, - 'lt' => 9.46558864129363E-01 - ), - 'gal' => array( 'tsp' => 7.68000000000000E+02, - 'tbs' => 2.56000000000000E+02, - 'oz' => 1.28000000000000E+02, - 'cup' => 1.60000000000000E+01, - 'pt' => 8.00000000000000E+00, - 'us_pt' => 8.00000000000000E+00, - 'uk_pt' => 6.66284940919265E+00, - 'qt' => 4.00000000000000E+00, - 'gal' => 1.0, - 'l' => 3.78623545651745E+00, - 'lt' => 3.78623545651745E+00 - ), - 'l' => array( 'tsp' => 2.02840000000000E+02, - 'tbs' => 6.76133333333333E+01, - 'oz' => 3.38066666666667E+01, - 'cup' => 4.22583333333333E+00, - 'pt' => 2.11291666666667E+00, - 'us_pt' => 2.11291666666667E+00, - 'uk_pt' => 1.75975569552166E+00, - 'qt' => 1.05645833333333E+00, - 'gal' => 2.64114583333333E-01, - 'l' => 1.0, - 'lt' => 1.0 - ), - 'lt' => array( 'tsp' => 2.02840000000000E+02, - 'tbs' => 6.76133333333333E+01, - 'oz' => 3.38066666666667E+01, - 'cup' => 4.22583333333333E+00, - 'pt' => 2.11291666666667E+00, - 'us_pt' => 2.11291666666667E+00, - 'uk_pt' => 1.75975569552166E+00, - 'qt' => 1.05645833333333E+00, - 'gal' => 2.64114583333333E-01, - 'l' => 1.0, - 'lt' => 1.0 - ) - ) - ); - - - /** - * getConversionGroups - * - * @return array - */ - public static function getConversionGroups() { - $conversionGroups = array(); - foreach(self::$_conversionUnits as $conversionUnit) { - $conversionGroups[] = $conversionUnit['Group']; - } - return array_merge(array_unique($conversionGroups)); - } // function getConversionGroups() - - - /** - * getConversionGroupUnits - * - * @return array - */ - public static function getConversionGroupUnits($group = NULL) { - $conversionGroups = array(); - foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) { - if ((is_null($group)) || ($conversionGroup['Group'] == $group)) { - $conversionGroups[$conversionGroup['Group']][] = $conversionUnit; - } - } - return $conversionGroups; - } // function getConversionGroupUnits() - - - /** - * getConversionGroupUnitDetails - * - * @return array - */ - public static function getConversionGroupUnitDetails($group = NULL) { - $conversionGroups = array(); - foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) { - if ((is_null($group)) || ($conversionGroup['Group'] == $group)) { - $conversionGroups[$conversionGroup['Group']][] = array( 'unit' => $conversionUnit, - 'description' => $conversionGroup['Unit Name'] - ); - } - } - return $conversionGroups; - } // function getConversionGroupUnitDetails() - - - /** - * getConversionGroups - * - * @return array - */ - public static function getConversionMultipliers() { - return self::$_conversionMultipliers; - } // function getConversionGroups() - - - /** - * CONVERTUOM - * - * @param float $value - * @param string $fromUOM - * @param string $toUOM - * @return float - */ - public static function CONVERTUOM($value, $fromUOM, $toUOM) { - $value = self::flattenSingleValue($value); - $fromUOM = self::flattenSingleValue($fromUOM); - $toUOM = self::flattenSingleValue($toUOM); - - if (!is_numeric($value)) { - return self::$_errorCodes['value']; - } - $fromMultiplier = 1; - if (isset(self::$_conversionUnits[$fromUOM])) { - $unitGroup1 = self::$_conversionUnits[$fromUOM]['Group']; - } else { - $fromMultiplier = substr($fromUOM,0,1); - $fromUOM = substr($fromUOM,1); - if (isset(self::$_conversionMultipliers[$fromMultiplier])) { - $fromMultiplier = self::$_conversionMultipliers[$fromMultiplier]['multiplier']; - } else { - return self::$_errorCodes['na']; - } - if ((isset(self::$_conversionUnits[$fromUOM])) && (self::$_conversionUnits[$fromUOM]['AllowPrefix'])) { - $unitGroup1 = self::$_conversionUnits[$fromUOM]['Group']; - } else { - return self::$_errorCodes['na']; - } - } - $value *= $fromMultiplier; - - $toMultiplier = 1; - if (isset(self::$_conversionUnits[$toUOM])) { - $unitGroup2 = self::$_conversionUnits[$toUOM]['Group']; - } else { - $toMultiplier = substr($toUOM,0,1); - $toUOM = substr($toUOM,1); - if (isset(self::$_conversionMultipliers[$toMultiplier])) { - $toMultiplier = self::$_conversionMultipliers[$toMultiplier]['multiplier']; - } else { - return self::$_errorCodes['na']; - } - if ((isset(self::$_conversionUnits[$toUOM])) && (self::$_conversionUnits[$toUOM]['AllowPrefix'])) { - $unitGroup2 = self::$_conversionUnits[$toUOM]['Group']; - } else { - return self::$_errorCodes['na']; - } - } - if ($unitGroup1 != $unitGroup2) { - return self::$_errorCodes['na']; - } - - if ($fromUOM == $toUOM) { - return 1.0; - } elseif ($unitGroup1 == 'Temperature') { - if (($fromUOM == 'F') || ($fromUOM == 'fah')) { - if (($toUOM == 'F') || ($toUOM == 'fah')) { - return 1.0; - } else { - $value = (($value - 32) / 1.8); - if (($toUOM == 'K') || ($toUOM == 'kel')) { - $value += 273.15; - } - return $value; - } - } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) && - (($toUOM == 'K') || ($toUOM == 'kel'))) { - return 1.0; - } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) && - (($toUOM == 'C') || ($toUOM == 'cel'))) { - return 1.0; - } - if (($toUOM == 'F') || ($toUOM == 'fah')) { - if (($fromUOM == 'K') || ($fromUOM == 'kel')) { - $value -= 273.15; - } - return ($value * 1.8) + 32; - } - if (($toUOM == 'C') || ($toUOM == 'cel')) { - return $value - 273.15; - } - return $value + 273.15; - } - return ($value * self::$_unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier; - } // function CONVERTUOM() - - - /** - * BESSELI - * - * Returns the modified Bessel function, which is equivalent to the Bessel function evaluated for purely imaginary arguments - * - * @param float $x - * @param float $n - * @return int - */ - public static function BESSELI($x, $n) { - $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); - $n = (is_null($n)) ? 0.0 : self::flattenSingleValue($n); - - if ((is_numeric($x)) && (is_numeric($n))) { - $n = floor($n); - if ($n < 0) { - return self::$_errorCodes['num']; - } - $f_2_PI = 2 * M_PI; - - if (abs($x) <= 30) { - $fTerm = pow($x / 2, $n) / self::FACT($n); - $nK = 1; - $fResult = $fTerm; - $fSqrX = ($x * $x) / 4; - do { - $fTerm *= $fSqrX; - $fTerm /= ($nK * ($nK + $n)); - $fResult += $fTerm; - } while ((abs($fTerm) > 1e-10) && (++$nK < 100)); - } else { - $fXAbs = abs($x); - $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs); - if (($n && 1) && ($x < 0)) { - $fResult = -$fResult; - } - } - return $fResult; - } - return self::$_errorCodes['value']; - } // function BESSELI() - - - /** - * BESSELJ - * - * Returns the Bessel function - * - * @param float $x - * @param float $n - * @return int - */ - public static function BESSELJ($x, $n) { - $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); - $n = (is_null($n)) ? 0.0 : self::flattenSingleValue($n); - - if ((is_numeric($x)) && (is_numeric($n))) { - $n = floor($n); - if ($n < 0) { - return self::$_errorCodes['num']; - } - $f_PI_DIV_2 = M_PI / 2; - $f_PI_DIV_4 = M_PI / 4; - - $fResult = 0; - if (abs($x) <= 30) { - $fTerm = pow($x / 2, $n) / self::FACT($n); - $nK = 1; - $fResult = $fTerm; - $fSqrX = ($x * $x) / -4; - do { - $fTerm *= $fSqrX; - $fTerm /= ($nK * ($nK + $n)); - $fResult += $fTerm; - } while ((abs($fTerm) > 1e-10) && (++$nK < 100)); - } else { - $fXAbs = abs($x); - $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $n * $f_PI_DIV_2 - $f_PI_DIV_4); - if (($n && 1) && ($x < 0)) { - $fResult = -$fResult; - } - } - return $fResult; - } - return self::$_errorCodes['value']; - } // function BESSELJ() - - - private static function _Besselk0($fNum) { - if ($fNum <= 2) { - $fNum2 = $fNum * 0.5; - $y = ($fNum2 * $fNum2); - $fRet = -log($fNum2) * self::BESSELI($fNum, 0) + - (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y * - (0.10750e-3 + $y * 0.74e-5)))))); - } else { - $y = 2 / $fNum; - $fRet = exp(-$fNum) / sqrt($fNum) * - (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y * - (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3)))))); - } - return $fRet; - } // function _Besselk0() - - - private static function _Besselk1($fNum) { - if ($fNum <= 2) { - $fNum2 = $fNum * 0.5; - $y = ($fNum2 * $fNum2); - $fRet = log($fNum2) * self::BESSELI($fNum, 1) + - (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y * - (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum; - } else { - $y = 2 / $fNum; - $fRet = exp(-$fNum) / sqrt($fNum) * - (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y * - (0.325614e-2 + $y * (-0.68245e-3))))))); - } - return $fRet; - } // function _Besselk1() - - - /** - * BESSELK - * - * Returns the modified Bessel function, which is equivalent to the Bessel functions evaluated for purely imaginary arguments. - * - * @param float $x - * @param float $ord - * @return float - */ - public static function BESSELK($x, $ord) { - $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); - $ord = (is_null($ord)) ? 0.0 : self::flattenSingleValue($ord); - - if ((is_numeric($x)) && (is_numeric($ord))) { - if (($ord < 0) || ($x == 0.0)) { - return self::$_errorCodes['num']; - } - - switch(floor($ord)) { - case 0 : return self::_Besselk0($x); - break; - case 1 : return self::_Besselk1($x); - break; - default : $fTox = 2 / $x; - $fBkm = self::_Besselk0($x); - $fBk = self::_Besselk1($x); - for ($n = 1; $n < $ord; ++$n) { - $fBkp = $fBkm + $n * $fTox * $fBk; - $fBkm = $fBk; - $fBk = $fBkp; - } - } - return $fBk; - } - return self::$_errorCodes['value']; - } // function BESSELK() - - - private static function _Bessely0($fNum) { - if ($fNum < 8.0) { - $y = ($fNum * $fNum); - $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733)))); - $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y)))); - $fRet = $f1 / $f2 + M_2DIVPI * self::BESSELJ($fNum, 0) * log($fNum); - } else { - $z = 8.0 / $fNum; - $y = ($z * $z); - $xx = $fNum - 0.785398164; - $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6))); - $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7)))); - $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); - } - return $fRet; - } // function _Bessely0() - - - private static function _Bessely1($fNum) { - if ($fNum < 8.0) { - $y = ($fNum * $fNum); - $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y * - (-0.4237922726e7 + $y * 0.8511937935e4))))); - $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y * - (0.1020426050e6 + $y * (0.3549632885e3 + $y))))); - $fRet = $f1 / $f2 + M_2DIVPI * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); - } else { - $z = 8.0 / $fNum; - $y = ($z * $z); - $xx = $fNum - 2.356194491; - $f1 = 1 + $y * (0.183105e-2 + $y * (-0.3516396496e-4 + $y * (0.2457520174e-5 + $y * (-0.240337019e6)))); - $f2 = 0.04687499995 + $y * (-0.2002690873e-3 + $y * (0.8449199096e-5 + $y * (-0.88228987e-6 + $y * 0.105787412e-6))); - $fRet = sqrt(M_2DIVPI / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); - #i12430# ...but this seems to work much better. -// $fRet = sqrt(M_2DIVPI / $fNum) * sin($fNum - 2.356194491); - } - return $fRet; - } // function _Bessely1() - - - /** - * BESSELY - * - * Returns the Bessel function, which is also called the Weber function or the Neumann function. - * - * @param float $x - * @param float $n - * @return int - */ - public static function BESSELY($x, $ord) { - $x = (is_null($x)) ? 0.0 : self::flattenSingleValue($x); - $ord = (is_null($ord)) ? 0.0 : self::flattenSingleValue($ord); - - if ((is_numeric($x)) && (is_numeric($ord))) { - if (($ord < 0) || ($x == 0.0)) { - return self::$_errorCodes['num']; - } - - switch(floor($ord)) { - case 0 : return self::_Bessely0($x); - break; - case 1 : return self::_Bessely1($x); - break; - default: $fTox = 2 / $x; - $fBym = self::_Bessely0($x); - $fBy = self::_Bessely1($x); - for ($n = 1; $n < $ord; ++$n) { - $fByp = $n * $fTox * $fBy - $fBym; - $fBym = $fBy; - $fBy = $fByp; - } - } - return $fBy; - } - return self::$_errorCodes['value']; - } // function BESSELY() - - - /** - * DELTA - * - * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise. - * - * @param float $a - * @param float $b - * @return int - */ - public static function DELTA($a, $b=0) { - $a = self::flattenSingleValue($a); - $b = self::flattenSingleValue($b); - - return (int) ($a == $b); - } // function DELTA() - - - /** - * GESTEP - * - * Returns 1 if number = step; returns 0 (zero) otherwise - * - * @param float $number - * @param float $step - * @return int - */ - public static function GESTEP($number, $step=0) { - $number = self::flattenSingleValue($number); - $step = self::flattenSingleValue($step); - - return (int) ($number >= $step); - } // function GESTEP() - - - // - // Private method to calculate the erf value - // - private static $_two_sqrtpi = 1.128379167095512574; - - private static function _erfVal($x) { - if (abs($x) > 2.2) { - return 1 - self::_erfcVal($x); - } - $sum = $term = $x; - $xsqr = ($x * $x); - $j = 1; - do { - $term *= $xsqr / $j; - $sum -= $term / (2 * $j + 1); - ++$j; - $term *= $xsqr / $j; - $sum += $term / (2 * $j + 1); - ++$j; - if ($sum == 0.0) { - break; - } - } while (abs($term / $sum) > PRECISION); - return self::$_two_sqrtpi * $sum; - } // function _erfVal() - - - /** - * ERF - * - * Returns the error function integrated between lower_limit and upper_limit - * - * @param float $lower lower bound for integrating ERF - * @param float $upper upper bound for integrating ERF. - * If omitted, ERF integrates between zero and lower_limit - * @return int - */ - public static function ERF($lower, $upper = null) { - $lower = self::flattenSingleValue($lower); - $upper = self::flattenSingleValue($upper); - - if (is_numeric($lower)) { - if ($lower < 0) { - return self::$_errorCodes['num']; - } - if (is_null($upper)) { - return self::_erfVal($lower); - } - if (is_numeric($upper)) { - if ($upper < 0) { - return self::$_errorCodes['num']; - } - return self::_erfVal($upper) - self::_erfVal($lower); - } - } - return self::$_errorCodes['value']; - } // function ERF() - - - // - // Private method to calculate the erfc value - // - private static $_one_sqrtpi = 0.564189583547756287; - - private static function _erfcVal($x) { - if (abs($x) < 2.2) { - return 1 - self::_erfVal($x); - } - if ($x < 0) { - return 2 - self::erfc(-$x); - } - $a = $n = 1; - $b = $c = $x; - $d = ($x * $x) + 0.5; - $q1 = $q2 = $b / $d; - $t = 0; - do { - $t = $a * $n + $b * $x; - $a = $b; - $b = $t; - $t = $c * $n + $d * $x; - $c = $d; - $d = $t; - $n += 0.5; - $q1 = $q2; - $q2 = $b / $d; - } while ((abs($q1 - $q2) / $q2) > PRECISION); - return self::$_one_sqrtpi * exp(-$x * $x) * $q2; - } // function _erfcVal() - - - /** - * ERFC - * - * Returns the complementary ERF function integrated between x and infinity - * - * @param float $x The lower bound for integrating ERF - * @return int - */ - public static function ERFC($x) { - $x = self::flattenSingleValue($x); - - if (is_numeric($x)) { - if ($x < 0) { - return self::$_errorCodes['num']; - } - return self::_erfcVal($x); - } - return self::$_errorCodes['value']; - } // function ERFC() - - - /** - * LOWERCASE - * - * Converts a string value to upper case. - * - * @param string $mixedCaseString - * @return string - */ - public static function LOWERCASE($mixedCaseString) { - $mixedCaseString = self::flattenSingleValue($mixedCaseString); - - if (is_bool($mixedCaseString)) { - $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_LOWER, 'UTF-8'); - } else { - return strtoupper($mixedCaseString); - } - } // function LOWERCASE() - - - /** - * UPPERCASE - * - * Converts a string value to upper case. - * - * @param string $mixedCaseString - * @return string - */ - public static function UPPERCASE($mixedCaseString) { - $mixedCaseString = self::flattenSingleValue($mixedCaseString); - - if (is_bool($mixedCaseString)) { - $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_UPPER, 'UTF-8'); - } else { - return strtoupper($mixedCaseString); - } - } // function UPPERCASE() - - - /** - * PROPERCASE - * - * Converts a string value to upper case. - * - * @param string $mixedCaseString - * @return string - */ - public static function PROPERCASE($mixedCaseString) { - $mixedCaseString = self::flattenSingleValue($mixedCaseString); - - if (is_bool($mixedCaseString)) { - $mixedCaseString = ($mixedCaseString) ? 'TRUE' : 'FALSE'; - } - - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_TITLE, 'UTF-8'); - } else { - return ucwords($mixedCaseString); - } - } // function PROPERCASE() - - - /** - * DOLLAR - * - * This function converts a number to text using currency format, with the decimals rounded to the specified place. - * The format used is $#,##0.00_);($#,##0.00).. - * - * @param float $value The value to format - * @param int $decimals The number of digits to display to the right of the decimal point. - * If decimals is negative, number is rounded to the left of the decimal point. - * If you omit decimals, it is assumed to be 2 - * @return string - */ - public static function DOLLAR($value = 0, $decimals = 2) { - $value = self::flattenSingleValue($value); - $decimals = is_null($decimals) ? 0 : self::flattenSingleValue($decimals); - - // Validate parameters - if (!is_numeric($value) || !is_numeric($decimals)) { - return self::$_errorCodes['num']; - } - $decimals = floor($decimals); - - if ($decimals > 0) { - return money_format('%.'.$decimals.'n',$value); - } else { - $round = pow(10,abs($decimals)); - if ($value < 0) { $round = 0-$round; } - $value = self::MROUND($value,$round); - // The implementation of money_format used if the standard PHP function is not available can't handle decimal places of 0, - // so we display to 1 dp and chop off that character and the decimal separator using substr - return substr(money_format('%.1n',$value),0,-2); - } - } // function DOLLAR() - - - /** - * DOLLARDE - * - * Converts a dollar price expressed as an integer part and a fraction part into a dollar price expressed as a decimal number. - * Fractional dollar numbers are sometimes used for security prices. - * - * @param float $fractional_dollar Fractional Dollar - * @param int $fraction Fraction - * @return float - */ - public static function DOLLARDE($fractional_dollar = Null, $fraction = 0) { - $fractional_dollar = self::flattenSingleValue($fractional_dollar); - $fraction = (int)self::flattenSingleValue($fraction); - - // Validate parameters - if (is_null($fractional_dollar) || $fraction < 0) { - return self::$_errorCodes['num']; - } - if ($fraction == 0) { - return self::$_errorCodes['divisionbyzero']; - } - - $dollars = floor($fractional_dollar); - $cents = fmod($fractional_dollar,1); - $cents /= $fraction; - $cents *= pow(10,ceil(log10($fraction))); - return $dollars + $cents; - } // function DOLLARDE() - - - /** - * DOLLARFR - * - * Converts a dollar price expressed as a decimal number into a dollar price expressed as a fraction. - * Fractional dollar numbers are sometimes used for security prices. - * - * @param float $decimal_dollar Decimal Dollar - * @param int $fraction Fraction - * @return float - */ - public static function DOLLARFR($decimal_dollar = Null, $fraction = 0) { - $decimal_dollar = self::flattenSingleValue($decimal_dollar); - $fraction = (int)self::flattenSingleValue($fraction); - - // Validate parameters - if (is_null($decimal_dollar) || $fraction < 0) { - return self::$_errorCodes['num']; - } - if ($fraction == 0) { - return self::$_errorCodes['divisionbyzero']; - } - - $dollars = floor($decimal_dollar); - $cents = fmod($decimal_dollar,1); - $cents *= $fraction; - $cents *= pow(10,-ceil(log10($fraction))); - return $dollars + $cents; - } // function DOLLARFR() - - - /** - * EFFECT - * - * Returns the effective interest rate given the nominal rate and the number of compounding payments per year. - * - * @param float $nominal_rate Nominal interest rate - * @param int $npery Number of compounding payments per year - * @return float - */ - public static function EFFECT($nominal_rate = 0, $npery = 0) { - $nominal_rate = self::flattenSingleValue($nominal_rate); - $npery = (int)self::flattenSingleValue($npery); - - // Validate parameters - if ($nominal_rate <= 0 || $npery < 1) { - return self::$_errorCodes['num']; - } - - return pow((1 + $nominal_rate / $npery), $npery) - 1; - } // function EFFECT() - - - /** - * NOMINAL - * - * Returns the nominal interest rate given the effective rate and the number of compounding payments per year. - * - * @param float $effect_rate Effective interest rate - * @param int $npery Number of compounding payments per year - * @return float - */ - public static function NOMINAL($effect_rate = 0, $npery = 0) { - $effect_rate = self::flattenSingleValue($effect_rate); - $npery = (int)self::flattenSingleValue($npery); - - // Validate parameters - if ($effect_rate <= 0 || $npery < 1) { - return self::$_errorCodes['num']; - } - - // Calculate - return $npery * (pow($effect_rate + 1, 1 / $npery) - 1); - } // function NOMINAL() - - - /** - * PV - * - * Returns the Present Value of a cash flow with constant payments and interest rate (annuities). - * - * @param float $rate Interest rate per period - * @param int $nper Number of periods - * @param float $pmt Periodic payment (annuity) - * @param float $fv Future Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $nper = self::flattenSingleValue($nper); - $pmt = self::flattenSingleValue($pmt); - $fv = self::flattenSingleValue($fv); - $type = self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - - // Calculate - if (!is_null($rate) && $rate != 0) { - return (-$pmt * (1 + $rate * $type) * ((pow(1 + $rate, $nper) - 1) / $rate) - $fv) / pow(1 + $rate, $nper); - } else { - return -$fv - $pmt * $nper; - } - } // function PV() - - - /** - * FV - * - * Returns the Future Value of a cash flow with constant payments and interest rate (annuities). - * - * @param float $rate Interest rate per period - * @param int $nper Number of periods - * @param float $pmt Periodic payment (annuity) - * @param float $pv Present Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $nper = self::flattenSingleValue($nper); - $pmt = self::flattenSingleValue($pmt); - $pv = self::flattenSingleValue($pv); - $type = self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - - // Calculate - if (!is_null($rate) && $rate != 0) { - return -$pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate * $type) * (pow(1 + $rate, $nper) - 1) / $rate; - } else { - return -$pv - $pmt * $nper; - } - } // function FV() - - - /** - * FVSCHEDULE - * - */ - public static function FVSCHEDULE($principal, $schedule) { - $principal = self::flattenSingleValue($principal); - $schedule = self::flattenArray($schedule); - - foreach($schedule as $n) { - $principal *= 1 + $n; - } - - return $principal; - } // function FVSCHEDULE() - - - /** - * PMT - * - * Returns the constant payment (annuity) for a cash flow with a constant interest rate. - * - * @param float $rate Interest rate per period - * @param int $nper Number of periods - * @param float $pv Present Value - * @param float $fv Future Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $nper = self::flattenSingleValue($nper); - $pv = self::flattenSingleValue($pv); - $fv = self::flattenSingleValue($fv); - $type = self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - - // Calculate - if (!is_null($rate) && $rate != 0) { - return (-$fv - $pv * pow(1 + $rate, $nper)) / (1 + $rate * $type) / ((pow(1 + $rate, $nper) - 1) / $rate); - } else { - return (-$pv - $fv) / $nper; - } - } // function PMT() - - - /** - * NPER - * - * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate. - * - * @param float $rate Interest rate per period - * @param int $pmt Periodic payment (annuity) - * @param float $pv Present Value - * @param float $fv Future Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $pmt = self::flattenSingleValue($pmt); - $pv = self::flattenSingleValue($pv); - $fv = self::flattenSingleValue($fv); - $type = self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - - // Calculate - if (!is_null($rate) && $rate != 0) { - if ($pmt == 0 && $pv == 0) { - return self::$_errorCodes['num']; - } - return log(($pmt * (1 + $rate * $type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate); - } else { - if ($pmt == 0) { - return self::$_errorCodes['num']; - } - return (-$pv -$fv) / $pmt; - } - } // function NPER() - - - - private static function _interestAndPrincipal($rate=0, $per=0, $nper=0, $pv=0, $fv=0, $type=0) { - $pmt = self::PMT($rate, $nper, $pv, $fv, $type); - $capital = $pv; - for ($i = 1; $i<= $per; ++$i) { - $interest = ($type && $i == 1)? 0 : -$capital * $rate; - $principal = $pmt - $interest; - $capital += $principal; - } - return array($interest, $principal); - } // function _interestAndPrincipal() - - - /** - * IPMT - * - * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate. - * - * @param float $rate Interest rate per period - * @param int $per Period for which we want to find the interest - * @param int $nper Number of periods - * @param float $pv Present Value - * @param float $fv Future Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $per = (int) self::flattenSingleValue($per); - $nper = (int) self::flattenSingleValue($nper); - $pv = self::flattenSingleValue($pv); - $fv = self::flattenSingleValue($fv); - $type = (int) self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - if ($per <= 0 || $per > $nper) { - return self::$_errorCodes['value']; - } - - // Calculate - $interestAndPrincipal = self::_interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type); - return $interestAndPrincipal[0]; - } // function IPMT() - - - /** - * CUMIPMT - * - * Returns the cumulative interest paid on a loan between start_period and end_period. - * - * @param float $rate Interest rate per period - * @param int $nper Number of periods - * @param float $pv Present Value - * @param int start The first period in the calculation. - * Payment periods are numbered beginning with 1. - * @param int end The last period in the calculation. - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0) { - $rate = self::flattenSingleValue($rate); - $nper = (int) self::flattenSingleValue($nper); - $pv = self::flattenSingleValue($pv); - $start = (int) self::flattenSingleValue($start); - $end = (int) self::flattenSingleValue($end); - $type = (int) self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - if ($start < 1 || $start > $end) { - return self::$_errorCodes['value']; - } - - // Calculate - $interest = 0; - for ($per = $start; $per <= $end; ++$per) { - $interest += self::IPMT($rate, $per, $nper, $pv, 0, $type); - } - - return $interest; - } // function CUMIPMT() - - - /** - * PPMT - * - * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate. - * - * @param float $rate Interest rate per period - * @param int $per Period for which we want to find the interest - * @param int $nper Number of periods - * @param float $pv Present Value - * @param float $fv Future Value - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { - $rate = self::flattenSingleValue($rate); - $per = (int) self::flattenSingleValue($per); - $nper = (int) self::flattenSingleValue($nper); - $pv = self::flattenSingleValue($pv); - $fv = self::flattenSingleValue($fv); - $type = (int) self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - if ($per <= 0 || $per > $nper) { - return self::$_errorCodes['value']; - } - - // Calculate - $interestAndPrincipal = self::_interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type); - return $interestAndPrincipal[1]; - } // function PPMT() - - - /** - * CUMPRINC - * - * Returns the cumulative principal paid on a loan between start_period and end_period. - * - * @param float $rate Interest rate per period - * @param int $nper Number of periods - * @param float $pv Present Value - * @param int start The first period in the calculation. - * Payment periods are numbered beginning with 1. - * @param int end The last period in the calculation. - * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period - * @return float - */ - public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0) { - $rate = self::flattenSingleValue($rate); - $nper = (int) self::flattenSingleValue($nper); - $pv = self::flattenSingleValue($pv); - $start = (int) self::flattenSingleValue($start); - $end = (int) self::flattenSingleValue($end); - $type = (int) self::flattenSingleValue($type); - - // Validate parameters - if ($type != 0 && $type != 1) { - return self::$_errorCodes['num']; - } - if ($start < 1 || $start > $end) { - return self::$_errorCodes['value']; - } - - // Calculate - $principal = 0; - for ($per = $start; $per <= $end; ++$per) { - $principal += self::PPMT($rate, $per, $nper, $pv, 0, $type); - } - - return $principal; - } // function CUMPRINC() - - - /** - * ISPMT - * - * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. - * - * Excel Function: - * =ISPMT(interest_rate, period, number_payments, PV) - * - * interest_rate is the interest rate for the investment - * - * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. - * - * number_payments is the number of payments for the annuity - * - * PV is the loan amount or present value of the payments - */ - public static function ISPMT() { - // Return value - $returnValue = 0; - - // Get the parameters - $aArgs = self::flattenArray(func_get_args()); - $interestRate = array_shift($aArgs); - $period = array_shift($aArgs); - $numberPeriods = array_shift($aArgs); - $principleRemaining = array_shift($aArgs); - - // Calculate - $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0); - for($i=0; $i <= $period; ++$i) { - $returnValue = $interestRate * $principleRemaining * -1; - $principleRemaining -= $principlePayment; - // principle needs to be 0 after the last payment, don't let floating point screw it up - if($i == $numberPeriods) { - $returnValue = 0; - } - } - return($returnValue); - } // function ISPMT() - - - /** - * NPV - * - * Returns the Net Present Value of a cash flow series given a discount rate. - * - * @param float Discount interest rate - * @param array Cash flow series - * @return float - */ - public static function NPV() { - // Return value - $returnValue = 0; - - // Loop through arguments - $aArgs = self::flattenArray(func_get_args()); - - // Calculate - $rate = array_shift($aArgs); - for ($i = 1; $i <= count($aArgs); ++$i) { - // Is it a numeric value? - if (is_numeric($aArgs[$i - 1])) { - $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i); - } - } - - // Return - return $returnValue; - } // function NPV() - - - /** - * XNPV - * - * Returns the net present value for a schedule of cash flows that is not necessarily periodic. - * To calculate the net present value for a series of cash flows that is periodic, use the NPV function. - * - * @param float Discount interest rate - * @param array Cash flow series - * @return float - */ - public static function XNPV($rate, $values, $dates) { - if ((!is_array($values)) || (!is_array($dates))) return self::$_errorCodes['value']; - $values = self::flattenArray($values); - $dates = self::flattenArray($dates); - $valCount = count($values); - if ($valCount != count($dates)) return self::$_errorCodes['num']; - - $xnpv = 0.0; - for ($i = 0; $i < $valCount; ++$i) { - $xnpv += $values[$i] / pow(1 + $rate, self::DATEDIF($dates[0],$dates[$i],'d') / 365); - } - return (is_finite($xnpv) ? $xnpv : self::$_errorCodes['value']); - } // function XNPV() - - - public static function IRR($values, $guess = 0.1) { - if (!is_array($values)) return self::$_errorCodes['value']; - $values = self::flattenArray($values); - $guess = self::flattenSingleValue($guess); - - // create an initial range, with a root somewhere between 0 and guess - $x1 = 0.0; - $x2 = $guess; - $f1 = self::NPV($x1, $values); - $f2 = self::NPV($x2, $values); - for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { - if (($f1 * $f2) < 0.0) break; - if (abs($f1) < abs($f2)) { - $f1 = self::NPV($x1 += 1.6 * ($x1 - $x2), $values); - } else { - $f2 = self::NPV($x2 += 1.6 * ($x2 - $x1), $values); - } - } - if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; - - $f = self::NPV($x1, $values); - if ($f < 0.0) { - $rtb = $x1; - $dx = $x2 - $x1; - } else { - $rtb = $x2; - $dx = $x1 - $x2; - } - - for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { - $dx *= 0.5; - $x_mid = $rtb + $dx; - $f_mid = self::NPV($x_mid, $values); - if ($f_mid <= 0.0) $rtb = $x_mid; - if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; - } - return self::$_errorCodes['value']; - } // function IRR() - - - public static function MIRR($values, $finance_rate, $reinvestment_rate) { - if (!is_array($values)) return self::$_errorCodes['value']; - $values = self::flattenArray($values); - $finance_rate = self::flattenSingleValue($finance_rate); - $reinvestment_rate = self::flattenSingleValue($reinvestment_rate); - $n = count($values); - - $rr = 1.0 + $reinvestment_rate; - $fr = 1.0 + $finance_rate; - - $npv_pos = $npv_neg = 0.0; - foreach($values as $i => $v) { - if ($v >= 0) { - $npv_pos += $v / pow($rr, $i); - } else { - $npv_neg += $v / pow($fr, $i); - } - } - - if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) { - return self::$_errorCodes['value']; - } - - $mirr = pow((-$npv_pos * pow($rr, $n)) - / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0; - - return (is_finite($mirr) ? $mirr : self::$_errorCodes['value']); - } // function MIRR() - - - public static function XIRR($values, $dates, $guess = 0.1) { - if ((!is_array($values)) && (!is_array($dates))) return self::$_errorCodes['value']; - $values = self::flattenArray($values); - $dates = self::flattenArray($dates); - $guess = self::flattenSingleValue($guess); - if (count($values) != count($dates)) return self::$_errorCodes['num']; - - // create an initial range, with a root somewhere between 0 and guess - $x1 = 0.0; - $x2 = $guess; - $f1 = self::XNPV($x1, $values, $dates); - $f2 = self::XNPV($x2, $values, $dates); - for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { - if (($f1 * $f2) < 0.0) break; - if (abs($f1) < abs($f2)) { - $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates); - } else { - $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates); - } - } - if (($f1 * $f2) > 0.0) return self::$_errorCodes['value']; - - $f = self::XNPV($x1, $values, $dates); - if ($f < 0.0) { - $rtb = $x1; - $dx = $x2 - $x1; - } else { - $rtb = $x2; - $dx = $x1 - $x2; - } - - for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { - $dx *= 0.5; - $x_mid = $rtb + $dx; - $f_mid = self::XNPV($x_mid, $values, $dates); - if ($f_mid <= 0.0) $rtb = $x_mid; - if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; - } - return self::$_errorCodes['value']; - } - - - /** - * RATE - * - **/ - public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { - $nper = (int) self::flattenSingleValue($nper); - $pmt = self::flattenSingleValue($pmt); - $pv = self::flattenSingleValue($pv); - $fv = (is_null($fv)) ? 0.0 : self::flattenSingleValue($fv); - $type = (is_null($type)) ? 0 : (int) self::flattenSingleValue($type); - $guess = (is_null($guess)) ? 0.1 : self::flattenSingleValue($guess); - - $rate = $guess; - if (abs($rate) < FINANCIAL_PRECISION) { - $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; - } else { - $f = exp($nper * log(1 + $rate)); - $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; - } - $y0 = $pv + $pmt * $nper + $fv; - $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; - - // find root by secant method - $i = $x0 = 0.0; - $x1 = $rate; - while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { - $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); - $x0 = $x1; - $x1 = $rate; - - if (abs($rate) < FINANCIAL_PRECISION) { - $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; - } else { - $f = exp($nper * log(1 + $rate)); - $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; - } - - $y0 = $y1; - $y1 = $y; - ++$i; - } - return $rate; - } // function RATE() - - - /** - * DB - * - * Returns the depreciation of an asset for a specified period using the fixed-declining balance method. - * This form of depreciation is used if you want to get a higher depreciation value at the beginning of the depreciation - * (as opposed to linear depreciation). The depreciation value is reduced with every depreciation period by the - * depreciation already deducted from the initial cost. - * - * @param float cost Initial cost of the asset. - * @param float salvage Value at the end of the depreciation. (Sometimes called the salvage value of the asset) - * @param int life Number of periods over which the asset is depreciated. (Sometimes called the useful life of the asset) - * @param int period The period for which you want to calculate the depreciation. Period must use the same units as life. - * @param float month Number of months in the first year. If month is omitted, it defaults to 12. - * @return float - */ - public static function DB($cost, $salvage, $life, $period, $month=12) { - $cost = (float) self::flattenSingleValue($cost); - $salvage = (float) self::flattenSingleValue($salvage); - $life = (int) self::flattenSingleValue($life); - $period = (int) self::flattenSingleValue($period); - $month = (int) self::flattenSingleValue($month); - - // Validate - if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month))) { - if ($cost == 0) { - return 0.0; - } elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1)) { - return self::$_errorCodes['num']; - } - // Set Fixed Depreciation Rate - $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); - $fixedDepreciationRate = round($fixedDepreciationRate, 3); - - // Loop through each period calculating the depreciation - $previousDepreciation = 0; - for ($per = 1; $per <= $period; ++$per) { - if ($per == 1) { - $depreciation = $cost * $fixedDepreciationRate * $month / 12; - } elseif ($per == ($life + 1)) { - $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12; - } else { - $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate; - } - $previousDepreciation += $depreciation; - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $depreciation = round($depreciation,2); - } - return $depreciation; - } - return self::$_errorCodes['value']; - } // function DB() - - - /** - * DDB - * - * Returns the depreciation of an asset for a specified period using the double-declining balance method or some other method you specify. - * - * @param float cost Initial cost of the asset. - * @param float salvage Value at the end of the depreciation. (Sometimes called the salvage value of the asset) - * @param int life Number of periods over which the asset is depreciated. (Sometimes called the useful life of the asset) - * @param int period The period for which you want to calculate the depreciation. Period must use the same units as life. - * @param float factor The rate at which the balance declines. - * If factor is omitted, it is assumed to be 2 (the double-declining balance method). - * @return float - */ - public static function DDB($cost, $salvage, $life, $period, $factor=2.0) { - $cost = (float) self::flattenSingleValue($cost); - $salvage = (float) self::flattenSingleValue($salvage); - $life = (int) self::flattenSingleValue($life); - $period = (int) self::flattenSingleValue($period); - $factor = (float) self::flattenSingleValue($factor); - - // Validate - if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor))) { - if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life)) { - return self::$_errorCodes['num']; - } - // Set Fixed Depreciation Rate - $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); - $fixedDepreciationRate = round($fixedDepreciationRate, 3); - - // Loop through each period calculating the depreciation - $previousDepreciation = 0; - for ($per = 1; $per <= $period; ++$per) { - $depreciation = min( ($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation) ); - $previousDepreciation += $depreciation; - } - if (self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) { - $depreciation = round($depreciation,2); - } - return $depreciation; - } - return self::$_errorCodes['value']; - } // function DDB() - - - private static function _daysPerYear($year,$basis) { - switch ($basis) { - case 0 : - case 2 : - case 4 : - $daysPerYear = 360; - break; - case 3 : - $daysPerYear = 365; - break; - case 1 : - if (self::_isLeapYear($year)) { - $daysPerYear = 366; - } else { - $daysPerYear = 365; - } - break; - default : - return self::$_errorCodes['num']; - } - return $daysPerYear; - } // function _daysPerYear() - - - /** - * ACCRINT - * - * Returns the discount rate for a security. - * - * @param mixed issue The security's issue date. - * @param mixed firstinter The security's first interest date. - * @param mixed settlement The security's settlement date. - * @param float rate The security's annual coupon rate. - * @param float par The security's par value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function ACCRINT($issue, $firstinter, $settlement, $rate, $par=1000, $frequency=1, $basis=0) { - $issue = self::flattenSingleValue($issue); - $firstinter = self::flattenSingleValue($firstinter); - $settlement = self::flattenSingleValue($settlement); - $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $frequency = (is_null($frequency)) ? 1 : (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($rate)) && (is_numeric($par))) { - if (($rate <= 0) || ($par <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenIssueAndSettlement = self::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { - return $daysBetweenIssueAndSettlement; - } - - return $par * $rate * $daysBetweenIssueAndSettlement; - } - return self::$_errorCodes['value']; - } // function ACCRINT() - - - /** - * ACCRINTM - * - * Returns the discount rate for a security. - * - * @param mixed issue The security's issue date. - * @param mixed settlement The security's settlement date. - * @param float rate The security's annual coupon rate. - * @param float par The security's par value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function ACCRINTM($issue, $settlement, $rate, $par=1000, $basis=0) { - $issue = self::flattenSingleValue($issue); - $settlement = self::flattenSingleValue($settlement); - $rate = (float) self::flattenSingleValue($rate); - $par = (is_null($par)) ? 1000 : (float) self::flattenSingleValue($par); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($rate)) && (is_numeric($par))) { - if (($rate <= 0) || ($par <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenIssueAndSettlement = self::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { - return $daysBetweenIssueAndSettlement; - } - return $par * $rate * $daysBetweenIssueAndSettlement; - } - return self::$_errorCodes['value']; - } // function ACCRINTM() - - - public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { - $cost = self::flattenSingleValue($cost); - $purchased = self::flattenSingleValue($purchased); - $firstPeriod = self::flattenSingleValue($firstPeriod); - $salvage = self::flattenSingleValue($salvage); - $period = floor(self::flattenSingleValue($period)); - $rate = self::flattenSingleValue($rate); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - $fUsePer = 1.0 / $rate; - - if ($fUsePer < 3.0) { - $amortiseCoeff = 1.0; - } elseif ($fUsePer < 5.0) { - $amortiseCoeff = 1.5; - } elseif ($fUsePer <= 6.0) { - $amortiseCoeff = 2.0; - } else { - $amortiseCoeff = 2.5; - } - - $rate *= $amortiseCoeff; -// $fNRate = floor((self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost) + 0.5); - $fNRate = round(self::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost,0); - $cost -= $fNRate; - $fRest = $cost - $salvage; - - for ($n = 0; $n < $period; ++$n) { -// $fNRate = floor(($rate * $cost) + 0.5); - $fNRate = round($rate * $cost,0); - $fRest -= $fNRate; - - if ($fRest < 0.0) { - switch ($period - $n) { - case 0 : - case 1 : -// return floor(($cost * 0.5) + 0.5); - return round($cost * 0.5,0); - break; - default : return 0.0; - break; - } - } - $cost -= $fNRate; - } - return $fNRate; - } // function AMORDEGRC() - - - public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { - $cost = self::flattenSingleValue($cost); - $purchased = self::flattenSingleValue($purchased); - $firstPeriod = self::flattenSingleValue($firstPeriod); - $salvage = self::flattenSingleValue($salvage); - $period = self::flattenSingleValue($period); - $rate = self::flattenSingleValue($rate); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - $fOneRate = $cost * $rate; - $fCostDelta = $cost - $salvage; - // Note, quirky variation for leap years on the YEARFRAC for this function - $purchasedYear = self::YEAR($purchased); - $yearFrac = self::YEARFRAC($purchased, $firstPeriod, $basis); - if (($basis == 1) && ($yearFrac < 1) && (self::_isLeapYear($purchasedYear))) { - $yearFrac *= 365 / 366; - } - $f0Rate = $yearFrac * $rate * $cost; - $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate); - - if ($period == 0) { - return $f0Rate; - } elseif ($period <= $nNumOfFullPeriods) { - return $fOneRate; - } elseif ($period == ($nNumOfFullPeriods + 1)) { - return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate); - } else { - return 0.0; - } - } // function AMORLINC() - - - private static function _lastDayOfMonth($testDate) { - $date = clone $testDate; - $date->modify('+1 day'); - return ($date->format('d') == 1); - } // function _lastDayOfMonth() - - private static function _firstDayOfMonth($testDate) { - $date = clone $testDate; - return ($date->format('d') == 1); - } // function _lastDayOfMonth() - - private static function _coupFirstPeriodDate($settlement, $maturity, $frequency, $next) { - $months = 12 / $frequency; - - $result = PHPExcel_Shared_Date::ExcelToPHPObject($maturity); - $eom = self::_lastDayOfMonth($result); - - while ($settlement < PHPExcel_Shared_Date::PHPToExcel($result)) { - $result->modify('-'.$months.' months'); - } - if ($next) { - $result->modify('+'.$months.' months'); - } - - if ($eom) { - $result->modify('-1 day'); - } - - return PHPExcel_Shared_Date::PHPToExcel($result); - } // function _coupFirstPeriodDate() - - - private static function _validFrequency($frequency) { - if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) { - return true; - } - if ((self::$compatibilityMode == self::COMPATIBILITY_GNUMERIC) && - (($frequency == 6) || ($frequency == 12))) { - return true; - } - return false; - } // function _validFrequency() - - public static function COUPDAYS($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - switch ($basis) { - case 3: // Actual/365 - return 365 / $frequency; - case 1: // Actual/actual - if ($frequency == 1) { - $daysPerYear = self::_daysPerYear(self::YEAR($maturity),$basis); - return ($daysPerYear / $frequency); - } else { - $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); - $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); - return ($next - $prev); - } - default: // US (NASD) 30/360, Actual/360 or European 30/360 - return 360 / $frequency; - } - return self::$_errorCodes['value']; - } // function COUPDAYS() - - - public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); - $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); - - return self::YEARFRAC($prev, $settlement, $basis) * $daysPerYear; - } // function COUPDAYBS() - - - public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); - $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); - - return self::YEARFRAC($settlement, $next, $basis) * $daysPerYear; - } // function COUPDAYSNC() - - - public static function COUPNCD($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); - } // function COUPNCD() - - - public static function COUPPCD($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); - } // function COUPPCD() - - - public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - $settlement = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis) * 365; - - switch ($frequency) { - case 1: // annual payments - return ceil($daysBetweenSettlementAndMaturity / 360); - case 2: // half-yearly - return ceil($daysBetweenSettlementAndMaturity / 180); - case 4: // quarterly - return ceil($daysBetweenSettlementAndMaturity / 90); - case 6: // bimonthly - return ceil($daysBetweenSettlementAndMaturity / 60); - case 12: // monthly - return ceil($daysBetweenSettlementAndMaturity / 30); - } - return self::$_errorCodes['value']; - } // function COUPNUM() - - - public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $rate = (float) self::flattenSingleValue($rate); - $yield = (float) self::flattenSingleValue($yield); - $redemption = (float) self::flattenSingleValue($redemption); - $frequency = (int) self::flattenSingleValue($frequency); - $basis = (is_null($basis)) ? 0 : (int) self::flattenSingleValue($basis); - - if (is_string($settlement = self::_getDateValue($settlement))) { - return self::$_errorCodes['value']; - } - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (($settlement > $maturity) || - (!self::_validFrequency($frequency)) || - (($basis < 0) || ($basis > 4))) { - return self::$_errorCodes['num']; - } - - $dsc = self::COUPDAYSNC($settlement, $maturity, $frequency, $basis); - $e = self::COUPDAYS($settlement, $maturity, $frequency, $basis); - $n = self::COUPNUM($settlement, $maturity, $frequency, $basis); - $a = self::COUPDAYBS($settlement, $maturity, $frequency, $basis); - - $baseYF = 1.0 + ($yield / $frequency); - $rfp = 100 * ($rate / $frequency); - $de = $dsc / $e; - - $result = $redemption / pow($baseYF, (--$n + $de)); - for($k = 0; $k <= $n; ++$k) { - $result += $rfp / (pow($baseYF, ($k + $de))); - } - $result -= $rfp * ($a / $e); - - return $result; - } // function PRICE() - - - /** - * DISC - * - * Returns the discount rate for a security. - * - * @param mixed settlement The security's settlement date. - * The security settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param int price The security's price per $100 face value. - * @param int redemption the security's redemption value per $100 face value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function DISC($settlement, $maturity, $price, $redemption, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $price = (float) self::flattenSingleValue($price); - $redemption = (float) self::flattenSingleValue($redemption); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($price)) && (is_numeric($redemption)) && (is_numeric($basis))) { - if (($price <= 0) || ($redemption <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - - return ((1 - $price / $redemption) / $daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function DISC() - - - /** - * PRICEDISC - * - * Returns the price per $100 face value of a discounted security. - * - * @param mixed settlement The security's settlement date. - * The security settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param int discount The security's discount rate. - * @param int redemption The security's redemption value per $100 face value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $discount = (float) self::flattenSingleValue($discount); - $redemption = (float) self::flattenSingleValue($redemption); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($discount)) && (is_numeric($redemption)) && (is_numeric($basis))) { - if (($discount <= 0) || ($redemption <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - - return $redemption * (1 - $discount * $daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function PRICEDISC() - - - /** - * PRICEMAT - * - * Returns the price per $100 face value of a security that pays interest at maturity. - * - * @param mixed settlement The security's settlement date. - * The security's settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param mixed issue The security's issue date. - * @param int rate The security's interest rate at date of issue. - * @param int yield The security's annual yield. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $issue = self::flattenSingleValue($issue); - $rate = self::flattenSingleValue($rate); - $yield = self::flattenSingleValue($yield); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if (is_numeric($rate) && is_numeric($yield)) { - if (($rate <= 0) || ($yield <= 0)) { - return self::$_errorCodes['num']; - } - $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); - if (!is_numeric($daysPerYear)) { - return $daysPerYear; - } - $daysBetweenIssueAndSettlement = self::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { - return $daysBetweenIssueAndSettlement; - } - $daysBetweenIssueAndSettlement *= $daysPerYear; - $daysBetweenIssueAndMaturity = self::YEARFRAC($issue, $maturity, $basis); - if (!is_numeric($daysBetweenIssueAndMaturity)) { - return $daysBetweenIssueAndMaturity; - } - $daysBetweenIssueAndMaturity *= $daysPerYear; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - $daysBetweenSettlementAndMaturity *= $daysPerYear; - - return ((100 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate * 100)) / - (1 + (($daysBetweenSettlementAndMaturity / $daysPerYear) * $yield)) - - (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate * 100)); - } - return self::$_errorCodes['value']; - } // function PRICEMAT() - - - /** - * RECEIVED - * - * Returns the price per $100 face value of a discounted security. - * - * @param mixed settlement The security's settlement date. - * The security settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param int investment The amount invested in the security. - * @param int discount The security's discount rate. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $investment = (float) self::flattenSingleValue($investment); - $discount = (float) self::flattenSingleValue($discount); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($investment)) && (is_numeric($discount)) && (is_numeric($basis))) { - if (($investment <= 0) || ($discount <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - - return $investment / ( 1 - ($discount * $daysBetweenSettlementAndMaturity)); - } - return self::$_errorCodes['value']; - } // function RECEIVED() - - - /** - * INTRATE - * - * Returns the interest rate for a fully invested security. - * - * @param mixed settlement The security's settlement date. - * The security settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param int investment The amount invested in the security. - * @param int redemption The amount to be received at maturity. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $investment = (float) self::flattenSingleValue($investment); - $redemption = (float) self::flattenSingleValue($redemption); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if ((is_numeric($investment)) && (is_numeric($redemption)) && (is_numeric($basis))) { - if (($investment <= 0) || ($redemption <= 0)) { - return self::$_errorCodes['num']; - } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - - return (($redemption / $investment) - 1) / ($daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function INTRATE() - - - /** - * TBILLEQ - * - * Returns the bond-equivalent yield for a Treasury bill. - * - * @param mixed settlement The Treasury bill's settlement date. - * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. - * @param mixed maturity The Treasury bill's maturity date. - * The maturity date is the date when the Treasury bill expires. - * @param int discount The Treasury bill's discount rate. - * @return float - */ - public static function TBILLEQ($settlement, $maturity, $discount) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $discount = self::flattenSingleValue($discount); - - // Use TBILLPRICE for validation - $testValue = self::TBILLPRICE($settlement, $maturity, $discount); - if (is_string($testValue)) { - return $testValue; - } - - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - ++$maturity; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; - } else { - $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); - } - - return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity); - } // function TBILLEQ() - - - /** - * TBILLPRICE - * - * Returns the yield for a Treasury bill. - * - * @param mixed settlement The Treasury bill's settlement date. - * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. - * @param mixed maturity The Treasury bill's maturity date. - * The maturity date is the date when the Treasury bill expires. - * @param int discount The Treasury bill's discount rate. - * @return float - */ - public static function TBILLPRICE($settlement, $maturity, $discount) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $discount = self::flattenSingleValue($discount); - - if (is_string($maturity = self::_getDateValue($maturity))) { - return self::$_errorCodes['value']; - } - - // Validate - if (is_numeric($discount)) { - if ($discount <= 0) { - return self::$_errorCodes['num']; - } - - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - ++$maturity; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - } else { - $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); - } - - if ($daysBetweenSettlementAndMaturity > 360) { - return self::$_errorCodes['num']; - } - - $price = 100 * (1 - (($discount * $daysBetweenSettlementAndMaturity) / 360)); - if ($price <= 0) { - return self::$_errorCodes['num']; - } - return $price; - } - return self::$_errorCodes['value']; - } // function TBILLPRICE() - - - /** - * TBILLYIELD - * - * Returns the yield for a Treasury bill. - * - * @param mixed settlement The Treasury bill's settlement date. - * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. - * @param mixed maturity The Treasury bill's maturity date. - * The maturity date is the date when the Treasury bill expires. - * @param int price The Treasury bill's price per $100 face value. - * @return float - */ - public static function TBILLYIELD($settlement, $maturity, $price) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $price = self::flattenSingleValue($price); - - // Validate - if (is_numeric($price)) { - if ($price <= 0) { - return self::$_errorCodes['num']; - } - - if (self::$compatibilityMode == self::COMPATIBILITY_OPENOFFICE) { - ++$maturity; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity) * 360; - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - } else { - $daysBetweenSettlementAndMaturity = (self::_getDateValue($maturity) - self::_getDateValue($settlement)); - } - - if ($daysBetweenSettlementAndMaturity > 360) { - return self::$_errorCodes['num']; - } - - return ((100 - $price) / $price) * (360 / $daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function TBILLYIELD() - - - /** - * SLN - * - * Returns the straight-line depreciation of an asset for one period - * - * @param cost Initial cost of the asset - * @param salvage Value at the end of the depreciation - * @param life Number of periods over which the asset is depreciated - * @return float - */ - public static function SLN($cost, $salvage, $life) { - $cost = self::flattenSingleValue($cost); - $salvage = self::flattenSingleValue($salvage); - $life = self::flattenSingleValue($life); - - // Calculate - if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life))) { - if ($life < 0) { - return self::$_errorCodes['num']; - } - return ($cost - $salvage) / $life; - } - return self::$_errorCodes['value']; - } // function SLN() - - - /** - * YIELDMAT - * - * Returns the annual yield of a security that pays interest at maturity. - * - * @param mixed settlement The security's settlement date. - * The security's settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param mixed issue The security's issue date. - * @param int rate The security's interest rate at date of issue. - * @param int price The security's price per $100 face value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $issue = self::flattenSingleValue($issue); - $rate = self::flattenSingleValue($rate); - $price = self::flattenSingleValue($price); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if (is_numeric($rate) && is_numeric($price)) { - if (($rate <= 0) || ($price <= 0)) { - return self::$_errorCodes['num']; - } - $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); - if (!is_numeric($daysPerYear)) { - return $daysPerYear; - } - $daysBetweenIssueAndSettlement = self::YEARFRAC($issue, $settlement, $basis); - if (!is_numeric($daysBetweenIssueAndSettlement)) { - return $daysBetweenIssueAndSettlement; - } - $daysBetweenIssueAndSettlement *= $daysPerYear; - $daysBetweenIssueAndMaturity = self::YEARFRAC($issue, $maturity, $basis); - if (!is_numeric($daysBetweenIssueAndMaturity)) { - return $daysBetweenIssueAndMaturity; - } - $daysBetweenIssueAndMaturity *= $daysPerYear; - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity, $basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - $daysBetweenSettlementAndMaturity *= $daysPerYear; - - return ((1 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate) - (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) / - (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) * - ($daysPerYear / $daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function YIELDMAT() - - - /** - * YIELDDISC - * - * Returns the annual yield of a security that pays interest at maturity. - * - * @param mixed settlement The security's settlement date. - * The security's settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. - * The maturity date is the date when the security expires. - * @param int price The security's price per $100 face value. - * @param int redemption The security's redemption value per $100 face value. - * @param int basis The type of day count to use. - * 0 or omitted US (NASD) 30/360 - * 1 Actual/actual - * 2 Actual/360 - * 3 Actual/365 - * 4 European 30/360 - * @return float - */ - public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis=0) { - $settlement = self::flattenSingleValue($settlement); - $maturity = self::flattenSingleValue($maturity); - $price = self::flattenSingleValue($price); - $redemption = self::flattenSingleValue($redemption); - $basis = (int) self::flattenSingleValue($basis); - - // Validate - if (is_numeric($price) && is_numeric($redemption)) { - if (($price <= 0) || ($redemption <= 0)) { - return self::$_errorCodes['num']; - } - $daysPerYear = self::_daysPerYear(self::YEAR($settlement),$basis); - if (!is_numeric($daysPerYear)) { - return $daysPerYear; - } - $daysBetweenSettlementAndMaturity = self::YEARFRAC($settlement, $maturity,$basis); - if (!is_numeric($daysBetweenSettlementAndMaturity)) { - return $daysBetweenSettlementAndMaturity; - } - $daysBetweenSettlementAndMaturity *= $daysPerYear; - - return (($redemption - $price) / $price) * ($daysPerYear / $daysBetweenSettlementAndMaturity); - } - return self::$_errorCodes['value']; - } // function YIELDDISC() - - - /** - * CELL_ADDRESS - * - * Creates a cell address as text, given specified row and column numbers. - * - * @param row Row number to use in the cell reference - * @param column Column number to use in the cell reference - * @param relativity Flag indicating the type of reference to return - * 1 or omitted Absolute - * 2 Absolute row; relative column - * 3 Relative row; absolute column - * 4 Relative - * @param referenceStyle A logical value that specifies the A1 or R1C1 reference style. - * TRUE or omitted CELL_ADDRESS returns an A1-style reference - * FALSE CELL_ADDRESS returns an R1C1-style reference - * @param sheetText Optional Name of worksheet to use - * @return string - */ - public static function CELL_ADDRESS($row, $column, $relativity=1, $referenceStyle=True, $sheetText='') { - $row = self::flattenSingleValue($row); - $column = self::flattenSingleValue($column); - $relativity = self::flattenSingleValue($relativity); - $sheetText = self::flattenSingleValue($sheetText); - - if (($row < 1) || ($column < 1)) { - return self::$_errorCodes['value']; - } - - if ($sheetText > '') { - if (strpos($sheetText,' ') !== False) { $sheetText = "'".$sheetText."'"; } - $sheetText .='!'; - } - if ((!is_bool($referenceStyle)) || $referenceStyle) { - $rowRelative = $columnRelative = '$'; - $column = PHPExcel_Cell::stringFromColumnIndex($column-1); - if (($relativity == 2) || ($relativity == 4)) { $columnRelative = ''; } - if (($relativity == 3) || ($relativity == 4)) { $rowRelative = ''; } - return $sheetText.$columnRelative.$column.$rowRelative.$row; - } else { - if (($relativity == 2) || ($relativity == 4)) { $column = '['.$column.']'; } - if (($relativity == 3) || ($relativity == 4)) { $row = '['.$row.']'; } - return $sheetText.'R'.$row.'C'.$column; - } - } // function CELL_ADDRESS() - - - /** - * COLUMN - * - * Returns the column number of the given cell reference - * If the cell reference is a range of cells, COLUMN returns the column numbers of each column in the reference as a horizontal array. - * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the - * reference of the cell in which the COLUMN function appears; otherwise this function returns 0. - * - * @param cellAddress A reference to a range of cells for which you want the column numbers - * @return integer or array of integer - */ - public static function COLUMN($cellAddress=Null) { - if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } - - if (is_array($cellAddress)) { - foreach($cellAddress as $columnKey => $value) { - $columnKey = preg_replace('/[^a-z]/i','',$columnKey); - return (integer) PHPExcel_Cell::columnIndexFromString($columnKey); - } - } else { - if (strpos($cellAddress,'!') !== false) { - list($sheet,$cellAddress) = explode('!',$cellAddress); - } - if (strpos($cellAddress,':') !== false) { - list($startAddress,$endAddress) = explode(':',$cellAddress); - $startAddress = preg_replace('/[^a-z]/i','',$startAddress); - $endAddress = preg_replace('/[^a-z]/i','',$endAddress); - $returnValue = array(); - do { - $returnValue[] = (integer) PHPExcel_Cell::columnIndexFromString($startAddress); - } while ($startAddress++ != $endAddress); - return $returnValue; - } else { - $cellAddress = preg_replace('/[^a-z]/i','',$cellAddress); - return (integer) PHPExcel_Cell::columnIndexFromString($cellAddress); - } - } - } // function COLUMN() - - - /** - * COLUMNS - * - * Returns the number of columns in an array or reference. - * - * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns - * @return integer - */ - public static function COLUMNS($cellAddress=Null) { - if (is_null($cellAddress) || $cellAddress === '') { - return 1; - } elseif (!is_array($cellAddress)) { - return self::$_errorCodes['value']; - } - - $x = array_keys($cellAddress); - $x = array_shift($x); - $isMatrix = (is_numeric($x)); - list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); - - if ($isMatrix) { - return $rows; - } else { - return $columns; - } - } // function COLUMNS() - - - /** - * ROW - * - * Returns the row number of the given cell reference - * If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference as a vertical array. - * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the - * reference of the cell in which the ROW function appears; otherwise this function returns 0. - * - * @param cellAddress A reference to a range of cells for which you want the row numbers - * @return integer or array of integer - */ - public static function ROW($cellAddress=Null) { - if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } - - if (is_array($cellAddress)) { - foreach($cellAddress as $columnKey => $rowValue) { - foreach($rowValue as $rowKey => $cellValue) { - return (integer) preg_replace('/[^0-9]/i','',$rowKey); - } - } - } else { - if (strpos($cellAddress,'!') !== false) { - list($sheet,$cellAddress) = explode('!',$cellAddress); - } - if (strpos($cellAddress,':') !== false) { - list($startAddress,$endAddress) = explode(':',$cellAddress); - $startAddress = preg_replace('/[^0-9]/','',$startAddress); - $endAddress = preg_replace('/[^0-9]/','',$endAddress); - $returnValue = array(); - do { - $returnValue[][] = (integer) $startAddress; - } while ($startAddress++ != $endAddress); - return $returnValue; - } else { - list($cellAddress) = explode(':',$cellAddress); - return (integer) preg_replace('/[^0-9]/','',$cellAddress); - } - } - } // function ROW() - - - /** - * ROWS - * - * Returns the number of rows in an array or reference. - * - * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows - * @return integer - */ - public static function ROWS($cellAddress=Null) { - if (is_null($cellAddress) || $cellAddress === '') { - return 1; - } elseif (!is_array($cellAddress)) { - return self::$_errorCodes['value']; - } - - $i = array_keys($cellAddress); - $isMatrix = (is_numeric(array_shift($i))); - list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); - - if ($isMatrix) { - return $columns; - } else { - return $rows; - } - } // function ROWS() - - - /** - * INDIRECT - * - * Returns the number of rows in an array or reference. - * - * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows - * @return integer - */ - public static function INDIRECT($cellAddress=Null, PHPExcel_Cell $pCell = null) { - $cellAddress = self::flattenSingleValue($cellAddress); - if (is_null($cellAddress) || $cellAddress === '') { - return self::REF(); - } - - $cellAddress1 = $cellAddress; - $cellAddress2 = NULL; - if (strpos($cellAddress,':') !== false) { - list($cellAddress1,$cellAddress2) = explode(':',$cellAddress); - } - - if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || - ((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { - return self::REF(); - } - - if (strpos($cellAddress,'!') !== false) { - list($sheetName,$cellAddress) = explode('!',$cellAddress); - $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); - } else { - $pSheet = $pCell->getParent(); - } - - return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); - } // function INDIRECT() - - - /** - * OFFSET - * - * Returns a reference to a range that is a specified number of rows and columns from a cell or range of cells. - * The reference that is returned can be a single cell or a range of cells. You can specify the number of rows and - * the number of columns to be returned. - * - * @param cellAddress The reference from which you want to base the offset. Reference must refer to a cell or - * range of adjacent cells; otherwise, OFFSET returns the #VALUE! error value. - * @param rows The number of rows, up or down, that you want the upper-left cell to refer to. - * Using 5 as the rows argument specifies that the upper-left cell in the reference is - * five rows below reference. Rows can be positive (which means below the starting reference) - * or negative (which means above the starting reference). - * @param cols The number of columns, to the left or right, that you want the upper-left cell of the result - * to refer to. Using 5 as the cols argument specifies that the upper-left cell in the - * reference is five columns to the right of reference. Cols can be positive (which means - * to the right of the starting reference) or negative (which means to the left of the - * starting reference). - * @param height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. - * @param width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. - * @return string A reference to a cell or range of cells - */ - public static function OFFSET($cellAddress=Null,$rows=0,$columns=0,$height=null,$width=null) { - $rows = self::flattenSingleValue($rows); - $columns = self::flattenSingleValue($columns); - $height = self::flattenSingleValue($height); - $width = self::flattenSingleValue($width); - if ($cellAddress == Null) { - return 0; - } - - $args = func_get_args(); - $pCell = array_pop($args); - if (!is_object($pCell)) { - return self::$_errorCodes['reference']; - } - - $sheetName = null; - if (strpos($cellAddress,"!")) { - list($sheetName,$cellAddress) = explode("!",$cellAddress); - } - if (strpos($cellAddress,":")) { - list($startCell,$endCell) = explode(":",$cellAddress); - } else { - $startCell = $endCell = $cellAddress; - } - list($startCellColumn,$startCellRow) = PHPExcel_Cell::coordinateFromString($startCell); - list($endCellColumn,$endCellRow) = PHPExcel_Cell::coordinateFromString($endCell); - - $startCellRow += $rows; - $startCellColumn = PHPExcel_Cell::columnIndexFromString($startCellColumn) - 1; - $startCellColumn += $columns; - - if (($startCellRow <= 0) || ($startCellColumn < 0)) { - return self::$_errorCodes['reference']; - } - $endCellColumn = PHPExcel_Cell::columnIndexFromString($endCellColumn) - 1; - if (($width != null) && (!is_object($width))) { - $endCellColumn = $startCellColumn + $width - 1; - } else { - $endCellColumn += $columns; - } - $startCellColumn = PHPExcel_Cell::stringFromColumnIndex($startCellColumn); - - if (($height != null) && (!is_object($height))) { - $endCellRow = $startCellRow + $height - 1; - } else { - $endCellRow += $rows; - } - - if (($endCellRow <= 0) || ($endCellColumn < 0)) { - return self::$_errorCodes['reference']; - } - $endCellColumn = PHPExcel_Cell::stringFromColumnIndex($endCellColumn); - - $cellAddress = $startCellColumn.$startCellRow; - if (($startCellColumn != $endCellColumn) || ($startCellRow != $endCellRow)) { - $cellAddress .= ':'.$endCellColumn.$endCellRow; - } - - if ($sheetName !== null) { - $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); - } else { - $pSheet = $pCell->getParent(); - } - - return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); - } // function OFFSET() - - - public static function CHOOSE() { - $chooseArgs = func_get_args(); - $chosenEntry = self::flattenArray(array_shift($chooseArgs)); - $entryCount = count($chooseArgs) - 1; - - if(is_array($chosenEntry)) { - $chosenEntry = array_shift($chosenEntry); - } - if ((is_numeric($chosenEntry)) && (!is_bool($chosenEntry))) { - --$chosenEntry; - } else { - return self::$_errorCodes['value']; - } - $chosenEntry = floor($chosenEntry); - if (($chosenEntry <= 0) || ($chosenEntry > $entryCount)) { - return self::$_errorCodes['value']; - } - - if (is_array($chooseArgs[$chosenEntry])) { - return self::flattenArray($chooseArgs[$chosenEntry]); - } else { - return $chooseArgs[$chosenEntry]; - } - } // function CHOOSE() - - - /** - * MATCH - * - * The MATCH function searches for a specified item in a range of cells - * - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_array The range of cells being searched - * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. - * @return integer The relative position of the found item - */ - public static function MATCH($lookup_value, $lookup_array, $match_type=1) { - $lookup_array = self::flattenArray($lookup_array); - $lookup_value = self::flattenSingleValue($lookup_value); - $match_type = (is_null($match_type)) ? 1 : (int) self::flattenSingleValue($match_type); - // MATCH is not case sensitive - $lookup_value = strtolower($lookup_value); - - // lookup_value type has to be number, text, or logical values - if ((!is_numeric($lookup_value)) && (!is_string($lookup_value)) && (!is_bool($lookup_value))) { - return self::$_errorCodes['na']; - } - - // match_type is 0, 1 or -1 - if (($match_type !== 0) && ($match_type !== -1) && ($match_type !== 1)) { - return self::$_errorCodes['na']; - } - - // lookup_array should not be empty - $lookupArraySize = count($lookup_array); - if ($lookupArraySize <= 0) { - return self::$_errorCodes['na']; - } - - // lookup_array should contain only number, text, or logical values, or empty (null) cells - foreach($lookup_array as $i => $lookupArrayValue) { - // check the type of the value - if ((!is_numeric($lookupArrayValue)) && (!is_string($lookupArrayValue)) && - (!is_bool($lookupArrayValue)) && (!is_null($lookupArrayValue))) { - return self::$_errorCodes['na']; - } - // convert strings to lowercase for case-insensitive testing - if (is_string($lookupArrayValue)) { - $lookup_array[$i] = strtolower($lookupArrayValue); - } - if ((is_null($lookupArrayValue)) && (($match_type == 1) || ($match_type == -1))) { - $lookup_array = array_slice($lookup_array,0,$i-1); - } - } - - // if match_type is 1 or -1, the list has to be ordered - if ($match_type == 1) { - asort($lookup_array); - $keySet = array_keys($lookup_array); - } elseif($match_type == -1) { - arsort($lookup_array); - $keySet = array_keys($lookup_array); - } - - // ** - // find the match - // ** - // loop on the cells -// var_dump($lookup_array); -// echo '
'; - foreach($lookup_array as $i => $lookupArrayValue) { - if (($match_type == 0) && ($lookupArrayValue == $lookup_value)) { - // exact match - return ++$i; - } elseif (($match_type == -1) && ($lookupArrayValue <= $lookup_value)) { -// echo '$i = '.$i.' => '; -// var_dump($lookupArrayValue); -// echo '
'; -// echo 'Keyset = '; -// var_dump($keySet); -// echo '
'; - $i = array_search($i,$keySet); -// echo '$i='.$i.'
'; - // if match_type is -1 <=> find the smallest value that is greater than or equal to lookup_value - if ($i < 1){ - // 1st cell was allready smaller than the lookup_value - break; - } else { - // the previous cell was the match - return $keySet[$i-1]+1; - } - } elseif (($match_type == 1) && ($lookupArrayValue >= $lookup_value)) { -// echo '$i = '.$i.' => '; -// var_dump($lookupArrayValue); -// echo '
'; -// echo 'Keyset = '; -// var_dump($keySet); -// echo '
'; - $i = array_search($i,$keySet); -// echo '$i='.$i.'
'; - // if match_type is 1 <=> find the largest value that is less than or equal to lookup_value - if ($i < 1){ - // 1st cell was allready bigger than the lookup_value - break; - } else { - // the previous cell was the match - return $keySet[$i-1]+1; - } - } - } - - // unsuccessful in finding a match, return #N/A error value - return self::$_errorCodes['na']; - } // function MATCH() - - - /** - * INDEX - * - * Uses an index to choose a value from a reference or array - * implemented: Return the value of a specified cell or array of cells Array form - * not implemented: Return a reference to specified cells Reference form - * - * @param range_array a range of cells or an array constant - * @param row_num selects the row in array from which to return a value. If row_num is omitted, column_num is required. - * @param column_num selects the column in array from which to return a value. If column_num is omitted, row_num is required. - */ - public static function INDEX($arrayValues,$rowNum = 0,$columnNum = 0) { - - if (($rowNum < 0) || ($columnNum < 0)) { - return self::$_errorCodes['value']; - } - - if (!is_array($arrayValues)) { - return self::$_errorCodes['reference']; - } - - $rowKeys = array_keys($arrayValues); - $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); - - if ($columnNum > count($columnKeys)) { - return self::$_errorCodes['value']; - } elseif ($columnNum == 0) { - if ($rowNum == 0) { - return $arrayValues; - } - $rowNum = $rowKeys[--$rowNum]; - $returnArray = array(); - foreach($arrayValues as $arrayColumn) { - if (is_array($arrayColumn)) { - if (isset($arrayColumn[$rowNum])) { - $returnArray[] = $arrayColumn[$rowNum]; - } else { - return $arrayValues[$rowNum]; - } - } else { - return $arrayValues[$rowNum]; - } - } - return $returnArray; - } - $columnNum = $columnKeys[--$columnNum]; - if ($rowNum > count($rowKeys)) { - return self::$_errorCodes['value']; - } elseif ($rowNum == 0) { - return $arrayValues[$columnNum]; - } - $rowNum = $rowKeys[--$rowNum]; - - return $arrayValues[$rowNum][$columnNum]; - } // function INDEX() - - /** * N * @@ -11379,435 +585,6 @@ class PHPExcel_Calculation_Functions { } // function TYPE() - /** - * SYD - * - * Returns the sum-of-years' digits depreciation of an asset for a specified period. - * - * @param cost Initial cost of the asset - * @param salvage Value at the end of the depreciation - * @param life Number of periods over which the asset is depreciated - * @param period Period - * @return float - */ - public static function SYD($cost, $salvage, $life, $period) { - $cost = self::flattenSingleValue($cost); - $salvage = self::flattenSingleValue($salvage); - $life = self::flattenSingleValue($life); - $period = self::flattenSingleValue($period); - - // Calculate - if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) { - if (($life < 1) || ($period > $life)) { - return self::$_errorCodes['num']; - } - return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1)); - } - return self::$_errorCodes['value']; - } // function SYD() - - - /** - * TRANSPOSE - * - * @param array $matrixData A matrix of values - * @return array - * - * Unlike the Excel TRANSPOSE function, which will only work on a single row or column, this function will transpose a full matrix. - */ - public static function TRANSPOSE($matrixData) { - $returnMatrix = array(); - if (!is_array($matrixData)) { $matrixData = array(array($matrixData)); } - - $column = 0; - foreach($matrixData as $matrixRow) { - $row = 0; - foreach($matrixRow as $matrixCell) { - $returnMatrix[$row][$column] = $matrixCell; - ++$row; - } - ++$column; - } - return $returnMatrix; - } // function TRANSPOSE() - - - /** - * MMULT - * - * @param array $matrixData1 A matrix of values - * @param array $matrixData2 A matrix of values - * @return array - */ - public static function MMULT($matrixData1,$matrixData2) { - $matrixAData = $matrixBData = array(); - if (!is_array($matrixData1)) { $matrixData1 = array(array($matrixData1)); } - if (!is_array($matrixData2)) { $matrixData2 = array(array($matrixData2)); } - - $rowA = 0; - foreach($matrixData1 as $matrixRow) { - $columnA = 0; - foreach($matrixRow as $matrixCell) { - if ((is_string($matrixCell)) || ($matrixCell === null)) { - return self::$_errorCodes['value']; - } - $matrixAData[$rowA][$columnA] = $matrixCell; - ++$columnA; - } - ++$rowA; - } - try { - $matrixA = new Matrix($matrixAData); - $rowB = 0; - foreach($matrixData2 as $matrixRow) { - $columnB = 0; - foreach($matrixRow as $matrixCell) { - if ((is_string($matrixCell)) || ($matrixCell === null)) { - return self::$_errorCodes['value']; - } - $matrixBData[$rowB][$columnB] = $matrixCell; - ++$columnB; - } - ++$rowB; - } - $matrixB = new Matrix($matrixBData); - - if (($rowA != $columnB) || ($rowB != $columnA)) { - return self::$_errorCodes['value']; - } - - return $matrixA->times($matrixB)->getArray(); - } catch (Exception $ex) { - return self::$_errorCodes['value']; - } - } // function MMULT() - - - /** - * MINVERSE - * - * @param array $matrixValues A matrix of values - * @return array - */ - public static function MINVERSE($matrixValues) { - $matrixData = array(); - if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); } - - $row = $maxColumn = 0; - foreach($matrixValues as $matrixRow) { - $column = 0; - foreach($matrixRow as $matrixCell) { - if ((is_string($matrixCell)) || ($matrixCell === null)) { - return self::$_errorCodes['value']; - } - $matrixData[$column][$row] = $matrixCell; - ++$column; - } - if ($column > $maxColumn) { $maxColumn = $column; } - ++$row; - } - if ($row != $maxColumn) { return self::$_errorCodes['value']; } - - try { - $matrix = new Matrix($matrixData); - return $matrix->inverse()->getArray(); - } catch (Exception $ex) { - return self::$_errorCodes['value']; - } - } // function MINVERSE() - - - /** - * MDETERM - * - * @param array $matrixValues A matrix of values - * @return float - */ - public static function MDETERM($matrixValues) { - $matrixData = array(); - if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); } - - $row = $maxColumn = 0; - foreach($matrixValues as $matrixRow) { - $column = 0; - foreach($matrixRow as $matrixCell) { - if ((is_string($matrixCell)) || ($matrixCell === null)) { - return self::$_errorCodes['value']; - } - $matrixData[$column][$row] = $matrixCell; - ++$column; - } - if ($column > $maxColumn) { $maxColumn = $column; } - ++$row; - } - if ($row != $maxColumn) { return self::$_errorCodes['value']; } - - try { - $matrix = new Matrix($matrixData); - return $matrix->det(); - } catch (Exception $ex) { - return self::$_errorCodes['value']; - } - } // function MDETERM() - - - /** - * SUMPRODUCT - * - * @param mixed $value Value to check - * @return float - */ - public static function SUMPRODUCT() { - $arrayList = func_get_args(); - - $wrkArray = self::flattenArray(array_shift($arrayList)); - $wrkCellCount = count($wrkArray); - - foreach($arrayList as $matrixData) { - $array2 = self::flattenArray($matrixData); - $count = count($array2); - if ($wrkCellCount != $count) { - return self::$_errorCodes['value']; - } - - foreach ($array2 as $i => $val) { - if (((is_numeric($wrkArray[$i])) && (!is_string($wrkArray[$i]))) && - ((is_numeric($val)) && (!is_string($val)))) { - $wrkArray[$i] *= $val; - } - } - } - - return array_sum($wrkArray); - } // function SUMPRODUCT() - - - /** - * SUMX2MY2 - * - * @param mixed $value Value to check - * @return float - */ - public static function SUMX2MY2($matrixData1,$matrixData2) { - $array1 = self::flattenArray($matrixData1); - $array2 = self::flattenArray($matrixData2); - $count1 = count($array1); - $count2 = count($array2); - if ($count1 < $count2) { - $count = $count1; - } else { - $count = $count2; - } - - $result = 0; - for ($i = 0; $i < $count; ++$i) { - if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && - ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { - $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]); - } - } - - return $result; - } // function SUMX2MY2() - - - /** - * SUMX2PY2 - * - * @param mixed $value Value to check - * @return float - */ - public static function SUMX2PY2($matrixData1,$matrixData2) { - $array1 = self::flattenArray($matrixData1); - $array2 = self::flattenArray($matrixData2); - $count1 = count($array1); - $count2 = count($array2); - if ($count1 < $count2) { - $count = $count1; - } else { - $count = $count2; - } - - $result = 0; - for ($i = 0; $i < $count; ++$i) { - if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && - ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { - $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]); - } - } - - return $result; - } // function SUMX2PY2() - - - /** - * SUMXMY2 - * - * @param mixed $value Value to check - * @return float - */ - public static function SUMXMY2($matrixData1,$matrixData2) { - $array1 = self::flattenArray($matrixData1); - $array2 = self::flattenArray($matrixData2); - $count1 = count($array1); - $count2 = count($array2); - if ($count1 < $count2) { - $count = $count1; - } else { - $count = $count2; - } - - $result = 0; - for ($i = 0; $i < $count; ++$i) { - if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && - ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { - $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]); - } - } - - return $result; - } // function SUMXMY2() - - - private static function _vlookupSort($a,$b) { - $f = array_keys($a); - $firstColumn = array_shift($f); - if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) { - return 0; - } - return (strtolower($a[$firstColumn]) < strtolower($b[$firstColumn])) ? -1 : 1; - } // function _vlookupSort() - - - /** - * VLOOKUP - * The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value in the same row based on the index_number. - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_array The range of cells being searched - * @param index_number The column number in table_array from which the matching value must be returned. The first column is 1. - * @param not_exact_match Determines if you are looking for an exact match based on lookup_value. - * @return mixed The value of the found cell - */ - public static function VLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match=true) { - $lookup_value = self::flattenSingleValue($lookup_value); - $index_number = self::flattenSingleValue($index_number); - $not_exact_match = self::flattenSingleValue($not_exact_match); - - // index_number must be greater than or equal to 1 - if ($index_number < 1) { - return self::$_errorCodes['value']; - } - - // index_number must be less than or equal to the number of columns in lookup_array - if ((!is_array($lookup_array)) || (count($lookup_array) < 1)) { - return self::$_errorCodes['reference']; - } else { - $f = array_keys($lookup_array); - $firstRow = array_pop($f); - if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { - return self::$_errorCodes['reference']; - } else { - $columnKeys = array_keys($lookup_array[$firstRow]); - $returnColumn = $columnKeys[--$index_number]; - $firstColumn = array_shift($columnKeys); - } - } - - if (!$not_exact_match) { - uasort($lookup_array,array('self','_vlookupSort')); - } - - $rowNumber = $rowValue = False; - foreach($lookup_array as $rowKey => $rowData) { - if (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)) { - break; - } - $rowNumber = $rowKey; - $rowValue = $rowData[$firstColumn]; - } - - if ($rowNumber !== false) { - if ((!$not_exact_match) && ($rowValue != $lookup_value)) { - // if an exact match is required, we have what we need to return an appropriate response - return self::$_errorCodes['na']; - } else { - // otherwise return the appropriate value - return $lookup_array[$rowNumber][$returnColumn]; - } - } - - return self::$_errorCodes['na']; - } // function VLOOKUP() - - - /** - * LOOKUP - * The LOOKUP function searches for value either from a one-row or one-column range or from an array. - * @param lookup_value The value that you want to match in lookup_array - * @param lookup_vector The range of cells being searched - * @param result_vector The column from which the matching value must be returned - * @return mixed The value of the found cell - */ - public static function LOOKUP($lookup_value, $lookup_vector, $result_vector=null) { - $lookup_value = self::flattenSingleValue($lookup_value); - - if (!is_array($lookup_vector)) { - return self::$_errorCodes['na']; - } - $lookupRows = count($lookup_vector); - $l = array_keys($lookup_vector); - $l = array_shift($l); - $lookupColumns = count($lookup_vector[$l]); - if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { - $lookup_vector = self::TRANSPOSE($lookup_vector); - $lookupRows = count($lookup_vector); - $l = array_keys($lookup_vector); - $lookupColumns = count($lookup_vector[array_shift($l)]); - } - - if (is_null($result_vector)) { - $result_vector = $lookup_vector; - } - $resultRows = count($result_vector); - $l = array_keys($result_vector); - $l = array_shift($l); - $resultColumns = count($result_vector[$l]); - if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { - $result_vector = self::TRANSPOSE($result_vector); - $resultRows = count($result_vector); - $r = array_keys($result_vector); - $resultColumns = count($result_vector[array_shift($r)]); - } - - if ($lookupRows == 2) { - $result_vector = array_pop($lookup_vector); - $lookup_vector = array_shift($lookup_vector); - } - if ($lookupColumns != 2) { - foreach($lookup_vector as &$value) { - if (is_array($value)) { - $k = array_keys($value); - $key1 = $key2 = array_shift($k); - $key2++; - $dataValue1 = $value[$key1]; - } else { - $key1 = 0; - $key2 = 1; - $dataValue1 = $value; - } - $dataValue2 = array_shift($result_vector); - if (is_array($dataValue2)) { - $dataValue2 = array_shift($dataValue2); - } - $value = array($key1 => $dataValue1, $key2 => $dataValue2); - } - unset($value); - } - - return self::VLOOKUP($lookup_value,$lookup_vector,2); - } // function LOOKUP() - - /** * Convert a multi-dimensional array to a simple 1-dimensional array * diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index c72cf06b..536c81fe 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -564,29 +564,17 @@ class PHPExcel_ReferenceHelper private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { // Get coordinates of $pBefore - $beforeColumn = 'A'; - $beforeRow = 1; list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); - // Get coordinates - $newColumn = 'A'; - $newRow = 1; + // Get coordinates of $pCellReference list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); - // Make sure the reference can be used - if ($newColumn == '' && $newRow == '') - { - return $pCellReference; - } - // Verify which parts should be updated - $updateColumn = (PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) - && (strpos($newColumn, '$') === false) - && (strpos($beforeColumn, '$') === false); + $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && + PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); - $updateRow = ($newRow >= $beforeRow) - && (strpos($newRow, '$') === false) - && (strpos($beforeRow, '$') === false); + $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && + $newRow >= $beforeRow); // Create new column reference if ($updateColumn) { diff --git a/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php b/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php index 4fd43f91..6c797a6c 100644 --- a/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php +++ b/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php @@ -18,7 +18,10 @@ * @version 1.1 * @license PHP v3.0 */ -class LUDecomposition { +class PHPExcel_Shared_JAMA_LUDecomposition { + + const MatrixSingularException = "Can only perform operation on singular matrix."; + const MatrixSquareException = "Mismatched Row dimension"; /** * Decomposition storage @@ -58,9 +61,9 @@ class LUDecomposition { * @return Structure to access L, U and piv. */ public function __construct($A) { - if ($A instanceof Matrix) { + if ($A instanceof PHPExcel_Shared_JAMA_Matrix) { // Use a "left-looking", dot-product, Crout/Doolittle algorithm. - $this->LU = $A->getArrayCopy(); + $this->LU = $A->getArray(); $this->m = $A->getRowDimension(); $this->n = $A->getColumnDimension(); for ($i = 0; $i < $this->m; ++$i) { @@ -112,7 +115,7 @@ class LUDecomposition { } } } else { - throw new Exception(JAMAError(ArgumentTypeException)); + throw new Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); } } // function __construct() @@ -134,7 +137,7 @@ class LUDecomposition { } } } - return new Matrix($L); + return new PHPExcel_Shared_JAMA_Matrix($L); } // function getL() @@ -153,7 +156,7 @@ class LUDecomposition { } } } - return new Matrix($U); + return new PHPExcel_Shared_JAMA_Matrix($U); } // function getU() @@ -205,7 +208,7 @@ class LUDecomposition { } return $d; } else { - throw new Exception(JAMAError(MatrixDimensionException)); + throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); } } // function det() @@ -245,11 +248,11 @@ class LUDecomposition { } return $X; } else { - throw new Exception(JAMAError(MatrixSingularException)); + throw new Exception(self::MatrixSingularException); } } else { - throw new Exception(JAMAError(MatrixSquareException)); + throw new Exception(self::MatrixSquareException); } } // function solve() -} // class LUDecomposition +} // class PHPExcel_Shared_JAMA_LUDecomposition diff --git a/Classes/PHPExcel/Shared/JAMA/Matrix.php b/Classes/PHPExcel/Shared/JAMA/Matrix.php index ffefee2c..aae40e4c 100644 --- a/Classes/PHPExcel/Shared/JAMA/Matrix.php +++ b/Classes/PHPExcel/Shared/JAMA/Matrix.php @@ -1017,6 +1017,23 @@ class PHPExcel_Shared_JAMA_Matrix { } // function concat() + /** + * Solve A*X = B. + * + * @param Matrix $B Right hand side + * @return Matrix ... Solution if A is square, least squares solution otherwise + */ + public function solve($B) { + if ($this->m == $this->n) { + $LU = new PHPExcel_Shared_JAMA_LUDecomposition($this); + return $LU->solve($B); + } else { + $QR = new QRDecomposition($this); + return $QR->solve($B); + } + } // function solve() + + /** * Matrix inverse or pseudoinverse. * @@ -1027,4 +1044,16 @@ class PHPExcel_Shared_JAMA_Matrix { } // function inverse() -} // class Matrix + /** + * det + * + * Calculate determinant + * @return float Determinant + */ + public function det() { + $L = new PHPExcel_Shared_JAMA_LUDecomposition($this); + return $L->det(); + } // function det() + + +} // class PHPExcel_Shared_JAMA_Matrix diff --git a/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php b/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php index 80680594..49293d7e 100644 --- a/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php +++ b/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php @@ -16,7 +16,9 @@ * @license PHP v3.0 * @version 1.1 */ -class QRDecomposition { +class PHPExcel_Shared_JAMA_QRDecomposition { + + const MatrixRankException = "Can only perform operation on full-rank matrix."; /** * Array for internal storage of decomposition. @@ -50,7 +52,7 @@ class QRDecomposition { * @return Structure to access R and the Householder vectors and compute Q. */ public function __construct($A) { - if($A instanceof Matrix) { + if($A instanceof PHPExcel_Shared_JAMA_Matrix) { // Initialize. $this->QR = $A->getArrayCopy(); $this->m = $A->getRowDimension(); @@ -86,7 +88,7 @@ class QRDecomposition { $this->Rdiag[$k] = -$nrm; } } else { - throw new Exception(JAMAError(ArgumentTypeException)); + throw new Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); } } // function __construct() @@ -121,7 +123,7 @@ class QRDecomposition { } } } - return new Matrix($H); + return new PHPExcel_Shared_JAMA_Matrix($H); } // function getH() @@ -142,7 +144,7 @@ class QRDecomposition { } } } - return new Matrix($R); + return new PHPExcel_Shared_JAMA_Matrix($R); } // function getR() @@ -179,7 +181,7 @@ class QRDecomposition { } } */ - return new Matrix($Q); + return new PHPExcel_Shared_JAMA_Matrix($Q); } // function getQ() @@ -219,14 +221,14 @@ class QRDecomposition { } } } - $X = new Matrix($X); + $X = new PHPExcel_Shared_JAMA_Matrix($X); return ($X->getMatrix(0, $this->n-1, 0, $nx)); } else { - throw new Exception(JAMAError(MatrixRankException)); + throw new Exception(self::MatrixRankException); } } else { - throw new Exception(JAMAError(MatrixDimensionException)); + throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); } } // function solve() -} // class QRDecomposition +} // PHPExcel_Shared_JAMA_class QRDecomposition diff --git a/Classes/PHPExcel/Style/NumberFormat.php b/Classes/PHPExcel/Style/NumberFormat.php index 2064602e..18feee25 100644 --- a/Classes/PHPExcel/Style/NumberFormat.php +++ b/Classes/PHPExcel/Style/NumberFormat.php @@ -644,7 +644,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $decimalLength = strlen($decimalPart); $decimalDivisor = pow(10,$decimalLength); - $GCD = PHPExcel_Calculation_Functions::GCD($decimalPart,$decimalDivisor); + $GCD = PHPExcel_Calculation_MathTrig::GCD($decimalPart,$decimalDivisor); $adjustedDecimalPart = $decimalPart/$GCD; $adjustedDecimalDivisor = $decimalDivisor/$GCD; diff --git a/Documentation/FunctionListByCategory.txt b/Documentation/FunctionListByCategory.txt index 27a7a9e3..bc840579 100644 --- a/Documentation/FunctionListByCategory.txt +++ b/Documentation/FunctionListByCategory.txt @@ -22,124 +22,124 @@ CATEGORY_DATABASE DVARP *** Not yet Implemented CATEGORY_DATE_AND_TIME - DATE PHPExcel_Calculation_Functions::DATE - DATEDIF PHPExcel_Calculation_Functions::DATEDIF - DATEVALUE PHPExcel_Calculation_Functions::DATEVALUE - DAY PHPExcel_Calculation_Functions::DAYOFMONTH - DAYS360 PHPExcel_Calculation_Functions::DAYS360 - EDATE PHPExcel_Calculation_Functions::EDATE - EOMONTH PHPExcel_Calculation_Functions::EOMONTH - HOUR PHPExcel_Calculation_Functions::HOUROFDAY - MINUTE PHPExcel_Calculation_Functions::MINUTEOFHOUR - MONTH PHPExcel_Calculation_Functions::MONTHOFYEAR - NETWORKDAYS PHPExcel_Calculation_Functions::NETWORKDAYS - NOW PHPExcel_Calculation_Functions::DATETIMENOW - SECOND PHPExcel_Calculation_Functions::SECONDOFMINUTE - TIME PHPExcel_Calculation_Functions::TIME - TIMEVALUE PHPExcel_Calculation_Functions::TIMEVALUE - TODAY PHPExcel_Calculation_Functions::DATENOW - WEEKDAY PHPExcel_Calculation_Functions::DAYOFWEEK - WEEKNUM PHPExcel_Calculation_Functions::WEEKOFYEAR - WORKDAY PHPExcel_Calculation_Functions::WORKDAY - YEAR PHPExcel_Calculation_Functions::YEAR - YEARFRAC PHPExcel_Calculation_Functions::YEARFRAC + DATE PHPExcel_Calculation_DateTime::DATE + DATEDIF PHPExcel_Calculation_DateTime::DATEDIF + DATEVALUE PHPExcel_Calculation_DateTime::DATEVALUE + DAY PHPExcel_Calculation_DateTime::DAYOFMONTH + DAYS360 PHPExcel_Calculation_DateTime::DAYS360 + EDATE PHPExcel_Calculation_DateTime::EDATE + EOMONTH PHPExcel_Calculation_DateTime::EOMONTH + HOUR PHPExcel_Calculation_DateTime::HOUROFDAY + MINUTE PHPExcel_Calculation_DateTime::MINUTEOFHOUR + MONTH PHPExcel_Calculation_DateTime::MONTHOFYEAR + NETWORKDAYS PHPExcel_Calculation_DateTime::NETWORKDAYS + NOW PHPExcel_Calculation_DateTime::DATETIMENOW + SECOND PHPExcel_Calculation_DateTime::SECONDOFMINUTE + TIME PHPExcel_Calculation_DateTime::TIME + TIMEVALUE PHPExcel_Calculation_DateTime::TIMEVALUE + TODAY PHPExcel_Calculation_DateTime::DATENOW + WEEKDAY PHPExcel_Calculation_DateTime::DAYOFWEEK + WEEKNUM PHPExcel_Calculation_DateTime::WEEKOFYEAR + WORKDAY PHPExcel_Calculation_DateTime::WORKDAY + YEAR PHPExcel_Calculation_DateTime::YEAR + YEARFRAC PHPExcel_Calculation_DateTime::YEARFRAC CATEGORY_ENGINEERING - BESSELI PHPExcel_Calculation_Functions::BESSELI - BESSELJ PHPExcel_Calculation_Functions::BESSELJ - BESSELK PHPExcel_Calculation_Functions::BESSELK - BESSELY PHPExcel_Calculation_Functions::BESSELY - BIN2DEC PHPExcel_Calculation_Functions::BINTODEC - BIN2HEX PHPExcel_Calculation_Functions::BINTOHEX - BIN2OCT PHPExcel_Calculation_Functions::BINTOOCT - COMPLEX PHPExcel_Calculation_Functions::COMPLEX - CONVERT PHPExcel_Calculation_Functions::CONVERTUOM - DEC2BIN PHPExcel_Calculation_Functions::DECTOBIN - DEC2HEX PHPExcel_Calculation_Functions::DECTOHEX - DEC2OCT PHPExcel_Calculation_Functions::DECTOOCT - DELTA PHPExcel_Calculation_Functions::DELTA - ERF PHPExcel_Calculation_Functions::ERF - ERFC PHPExcel_Calculation_Functions::ERFC - GESTEP PHPExcel_Calculation_Functions::GESTEP - HEX2BIN PHPExcel_Calculation_Functions::HEXTOBIN - HEX2DEC PHPExcel_Calculation_Functions::HEXTODEC - HEX2OCT PHPExcel_Calculation_Functions::HEXTOOCT - IMABS PHPExcel_Calculation_Functions::IMABS - IMAGINARY PHPExcel_Calculation_Functions::IMAGINARY - IMARGUMENT PHPExcel_Calculation_Functions::IMARGUMENT - IMCONJUGATE PHPExcel_Calculation_Functions::IMCONJUGATE - IMCOS PHPExcel_Calculation_Functions::IMCOS - IMDIV PHPExcel_Calculation_Functions::IMDIV - IMEXP PHPExcel_Calculation_Functions::IMEXP - IMLN PHPExcel_Calculation_Functions::IMLN - IMLOG10 PHPExcel_Calculation_Functions::IMLOG10 - IMLOG2 PHPExcel_Calculation_Functions::IMLOG2 - IMPOWER PHPExcel_Calculation_Functions::IMPOWER - IMPRODUCT PHPExcel_Calculation_Functions::IMPRODUCT - IMREAL PHPExcel_Calculation_Functions::IMREAL - IMSIN PHPExcel_Calculation_Functions::IMSIN - IMSQRT PHPExcel_Calculation_Functions::IMSQRT - IMSUB PHPExcel_Calculation_Functions::IMSUB - IMSUM PHPExcel_Calculation_Functions::IMSUM - OCT2BIN PHPExcel_Calculation_Functions::OCTTOBIN - OCT2DEC PHPExcel_Calculation_Functions::OCTTODEC - OCT2HEX PHPExcel_Calculation_Functions::OCTTOHEX + BESSELI PHPExcel_Calculation_Engineering::BESSELI + BESSELJ PHPExcel_Calculation_Engineering::BESSELJ + BESSELK PHPExcel_Calculation_Engineering::BESSELK + BESSELY PHPExcel_Calculation_Engineering::BESSELY + BIN2DEC PHPExcel_Calculation_Engineering::BINTODEC + BIN2HEX PHPExcel_Calculation_Engineering::BINTOHEX + BIN2OCT PHPExcel_Calculation_Engineering::BINTOOCT + COMPLEX PHPExcel_Calculation_Engineering::COMPLEX + CONVERT PHPExcel_Calculation_Engineering::CONVERTUOM + DEC2BIN PHPExcel_Calculation_Engineering::DECTOBIN + DEC2HEX PHPExcel_Calculation_Engineering::DECTOHEX + DEC2OCT PHPExcel_Calculation_Engineering::DECTOOCT + DELTA PHPExcel_Calculation_Engineering::DELTA + ERF PHPExcel_Calculation_Engineering::ERF + ERFC PHPExcel_Calculation_Engineering::ERFC + GESTEP PHPExcel_Calculation_Engineering::GESTEP + HEX2BIN PHPExcel_Calculation_Engineering::HEXTOBIN + HEX2DEC PHPExcel_Calculation_Engineering::HEXTODEC + HEX2OCT PHPExcel_Calculation_Engineering::HEXTOOCT + IMABS PHPExcel_Calculation_Engineering::IMABS + IMAGINARY PHPExcel_Calculation_Engineering::IMAGINARY + IMARGUMENT PHPExcel_Calculation_Engineering::IMARGUMENT + IMCONJUGATE PHPExcel_Calculation_Engineering::IMCONJUGATE + IMCOS PHPExcel_Calculation_Engineering::IMCOS + IMDIV PHPExcel_Calculation_Engineering::IMDIV + IMEXP PHPExcel_Calculation_Engineering::IMEXP + IMLN PHPExcel_Calculation_Engineering::IMLN + IMLOG10 PHPExcel_Calculation_Engineering::IMLOG10 + IMLOG2 PHPExcel_Calculation_Engineering::IMLOG2 + IMPOWER PHPExcel_Calculation_Engineering::IMPOWER + IMPRODUCT PHPExcel_Calculation_Engineering::IMPRODUCT + IMREAL PHPExcel_Calculation_Engineering::IMREAL + IMSIN PHPExcel_Calculation_Engineering::IMSIN + IMSQRT PHPExcel_Calculation_Engineering::IMSQRT + IMSUB PHPExcel_Calculation_Engineering::IMSUB + IMSUM PHPExcel_Calculation_Engineering::IMSUM + OCT2BIN PHPExcel_Calculation_Engineering::OCTTOBIN + OCT2DEC PHPExcel_Calculation_Engineering::OCTTODEC + OCT2HEX PHPExcel_Calculation_Engineering::OCTTOHEX CATEGORY_FINANCIAL - ACCRINT PHPExcel_Calculation_Functions::ACCRINT - ACCRINTM PHPExcel_Calculation_Functions::ACCRINTM - AMORDEGRC PHPExcel_Calculation_Functions::AMORDEGRC - AMORLINC PHPExcel_Calculation_Functions::AMORLINC - COUPDAYBS PHPExcel_Calculation_Functions::COUPDAYBS - COUPDAYS PHPExcel_Calculation_Functions::COUPDAYS - COUPDAYSNC PHPExcel_Calculation_Functions::COUPDAYSNC - COUPNCD PHPExcel_Calculation_Functions::COUPNCD - COUPNUM PHPExcel_Calculation_Functions::COUPNUM - COUPPCD PHPExcel_Calculation_Functions::COUPPCD - CUMIPMT PHPExcel_Calculation_Functions::CUMIPMT - CUMPRINC PHPExcel_Calculation_Functions::CUMPRINC - DB PHPExcel_Calculation_Functions::DB - DDB PHPExcel_Calculation_Functions::DDB - DISC PHPExcel_Calculation_Functions::DISC - DOLLARDE PHPExcel_Calculation_Functions::DOLLARDE - DOLLARFR PHPExcel_Calculation_Functions::DOLLARFR + ACCRINT PHPExcel_Calculation_Financial::ACCRINT + ACCRINTM PHPExcel_Calculation_Financial::ACCRINTM + AMORDEGRC PHPExcel_Calculation_Financial::AMORDEGRC + AMORLINC PHPExcel_Calculation_Financial::AMORLINC + COUPDAYBS PHPExcel_Calculation_Financial::COUPDAYBS + COUPDAYS PHPExcel_Calculation_Financial::COUPDAYS + COUPDAYSNC PHPExcel_Calculation_Financial::COUPDAYSNC + COUPNCD PHPExcel_Calculation_Financial::COUPNCD + COUPNUM PHPExcel_Calculation_Financial::COUPNUM + COUPPCD PHPExcel_Calculation_Financial::COUPPCD + CUMIPMT PHPExcel_Calculation_Financial::CUMIPMT + CUMPRINC PHPExcel_Calculation_Financial::CUMPRINC + DB PHPExcel_Calculation_Financial::DB + DDB PHPExcel_Calculation_Financial::DDB + DISC PHPExcel_Calculation_Financial::DISC + DOLLARDE PHPExcel_Calculation_Financial::DOLLARDE + DOLLARFR PHPExcel_Calculation_Financial::DOLLARFR DURATION *** Not yet Implemented - EFFECT PHPExcel_Calculation_Functions::EFFECT - FV PHPExcel_Calculation_Functions::FV - FVSCHEDULE PHPExcel_Calculation_Functions::FVSCHEDULE - INTRATE PHPExcel_Calculation_Functions::INTRATE - IPMT PHPExcel_Calculation_Functions::IPMT - IRR PHPExcel_Calculation_Functions::IRR - ISPMT PHPExcel_Calculation_Functions::ISPMT + EFFECT PHPExcel_Calculation_Financial::EFFECT + FV PHPExcel_Calculation_Financial::FV + FVSCHEDULE PHPExcel_Calculation_Financial::FVSCHEDULE + INTRATE PHPExcel_Calculation_Financial::INTRATE + IPMT PHPExcel_Calculation_Financial::IPMT + IRR PHPExcel_Calculation_Financial::IRR + ISPMT PHPExcel_Calculation_Financial::ISPMT MDURATION *** Not yet Implemented - MIRR PHPExcel_Calculation_Functions::MIRR - NOMINAL PHPExcel_Calculation_Functions::NOMINAL - NPER PHPExcel_Calculation_Functions::NPER - NPV PHPExcel_Calculation_Functions::NPV + MIRR PHPExcel_Calculation_Financial::MIRR + NOMINAL PHPExcel_Calculation_Financial::NOMINAL + NPER PHPExcel_Calculation_Financial::NPER + NPV PHPExcel_Calculation_Financial::NPV ODDFPRICE *** Not yet Implemented ODDFYIELD *** Not yet Implemented ODDLPRICE *** Not yet Implemented ODDLYIELD *** Not yet Implemented - PMT PHPExcel_Calculation_Functions::PMT - PPMT PHPExcel_Calculation_Functions::PPMT - PRICE PHPExcel_Calculation_Functions::PRICE - PRICEDISC PHPExcel_Calculation_Functions::PRICEDISC - PRICEMAT PHPExcel_Calculation_Functions::PRICEMAT - PV PHPExcel_Calculation_Functions::PV - RATE PHPExcel_Calculation_Functions::RATE - RECEIVED PHPExcel_Calculation_Functions::RECEIVED - SLN PHPExcel_Calculation_Functions::SLN - SYD PHPExcel_Calculation_Functions::SYD - TBILLEQ PHPExcel_Calculation_Functions::TBILLEQ - TBILLPRICE PHPExcel_Calculation_Functions::TBILLPRICE - TBILLYIELD PHPExcel_Calculation_Functions::TBILLYIELD + PMT PHPExcel_Calculation_Financial::PMT + PPMT PHPExcel_Calculation_Financial::PPMT + PRICE PHPExcel_Calculation_Financial::PRICE + PRICEDISC PHPExcel_Calculation_Financial::PRICEDISC + PRICEMAT PHPExcel_Calculation_Financial::PRICEMAT + PV PHPExcel_Calculation_Financial::PV + RATE PHPExcel_Calculation_Financial::RATE + RECEIVED PHPExcel_Calculation_Financial::RECEIVED + SLN PHPExcel_Calculation_Financial::SLN + SYD PHPExcel_Calculation_Financial::SYD + TBILLEQ PHPExcel_Calculation_Financial::TBILLEQ + TBILLPRICE PHPExcel_Calculation_Financial::TBILLPRICE + TBILLYIELD PHPExcel_Calculation_Financial::TBILLYIELD USDOLLAR *** Not yet Implemented VDB *** Not yet Implemented - XIRR PHPExcel_Calculation_Functions::XIRR - XNPV PHPExcel_Calculation_Functions::XNPV + XIRR PHPExcel_Calculation_Financial::XIRR + XNPV PHPExcel_Calculation_Financial::XNPV YIELD *** Not yet Implemented - YIELDDISC PHPExcel_Calculation_Functions::YIELDDISC - YIELDMAT PHPExcel_Calculation_Functions::YIELDMAT + YIELDDISC PHPExcel_Calculation_Financial::YIELDDISC + YIELDMAT PHPExcel_Calculation_Financial::YIELDMAT CATEGORY_INFORMATION CELL *** Not yet Implemented @@ -162,33 +162,33 @@ CATEGORY_INFORMATION VERSION PHPExcel_Calculation_Functions::VERSION CATEGORY_LOGICAL - AND PHPExcel_Calculation_Functions::LOGICAL_AND - FALSE PHPExcel_Calculation_Functions::LOGICAL_FALSE - IF PHPExcel_Calculation_Functions::STATEMENT_IF - IFERROR PHPExcel_Calculation_Functions::STATEMENT_IFERROR - NOT PHPExcel_Calculation_Functions::LOGICAL_NOT - OR PHPExcel_Calculation_Functions::LOGICAL_OR - TRUE PHPExcel_Calculation_Functions::LOGICAL_TRUE + AND PHPExcel_Calculation_Logical::LOGICAL_AND + FALSE PHPExcel_Calculation_Logical::FALSE + IF PHPExcel_Calculation_Logical::STATEMENT_IF + IFERROR PHPExcel_Calculation_Logical::IFERROR + NOT PHPExcel_Calculation_Logical::NOT + OR PHPExcel_Calculation_Logical::LOGICAL_OR + TRUE PHPExcel_Calculation_Logical::TRUE CATEGORY_LOOKUP_AND_REFERENCE - ADDRESS PHPExcel_Calculation_Functions::CELL_ADDRESS + ADDRESS PHPExcel_Calculation_LookupRef::CELL_ADDRESS AREAS *** Not yet Implemented - CHOOSE PHPExcel_Calculation_Functions::CHOOSE - COLUMN PHPExcel_Calculation_Functions::COLUMN - COLUMNS PHPExcel_Calculation_Functions::COLUMNS + CHOOSE PHPExcel_Calculation_LookupRef::CHOOSE + COLUMN PHPExcel_Calculation_LookupRef::COLUMN + COLUMNS PHPExcel_Calculation_LookupRef::COLUMNS GETPIVOTDATA *** Not yet Implemented HLOOKUP *** Not yet Implemented - HYPERLINK PHPExcel_Calculation_Functions::HYPERLINK - INDEX PHPExcel_Calculation_Functions::INDEX - INDIRECT PHPExcel_Calculation_Functions::INDIRECT - LOOKUP PHPExcel_Calculation_Functions::LOOKUP - MATCH PHPExcel_Calculation_Functions::MATCH - OFFSET PHPExcel_Calculation_Functions::OFFSET - ROW PHPExcel_Calculation_Functions::ROW - ROWS PHPExcel_Calculation_Functions::ROWS + HYPERLINK PHPExcel_Calculation_LookupRef::HYPERLINK + INDEX PHPExcel_Calculation_LookupRef::INDEX + INDIRECT PHPExcel_Calculation_LookupRef::INDIRECT + LOOKUP PHPExcel_Calculation_LookupRef::LOOKUP + MATCH PHPExcel_Calculation_LookupRef::MATCH + OFFSET PHPExcel_Calculation_LookupRef::OFFSET + ROW PHPExcel_Calculation_LookupRef::ROW + ROWS PHPExcel_Calculation_LookupRef::ROWS RTD *** Not yet Implemented - TRANSPOSE PHPExcel_Calculation_Functions::TRANSPOSE - VLOOKUP PHPExcel_Calculation_Functions::VLOOKUP + TRANSPOSE PHPExcel_Calculation_LookupRef::TRANSPOSE + VLOOKUP PHPExcel_Calculation_LookupRef::VLOOKUP CATEGORY_MATH_AND_TRIG ABS abs @@ -197,181 +197,181 @@ CATEGORY_MATH_AND_TRIG ASIN asin ASINH asinh ATAN atan - ATAN2 PHPExcel_Calculation_Functions::REVERSE_ATAN2 + ATAN2 PHPExcel_Calculation_MathTrig::REVERSE_ATAN2 ATANH atanh - CEILING PHPExcel_Calculation_Functions::CEILING - COMBIN PHPExcel_Calculation_Functions::COMBIN + CEILING PHPExcel_Calculation_MathTrig::CEILING + COMBIN PHPExcel_Calculation_MathTrig::COMBIN COS cos COSH cosh DEGREES rad2deg - EVEN PHPExcel_Calculation_Functions::EVEN + EVEN PHPExcel_Calculation_MathTrig::EVEN EXP exp - FACT PHPExcel_Calculation_Functions::FACT - FACTDOUBLE PHPExcel_Calculation_Functions::FACTDOUBLE - FLOOR PHPExcel_Calculation_Functions::FLOOR - GCD PHPExcel_Calculation_Functions::GCD - INT intval - LCM PHPExcel_Calculation_Functions::LCM + FACT PHPExcel_Calculation_MathTrig::FACT + FACTDOUBLE PHPExcel_Calculation_MathTrig::FACTDOUBLE + FLOOR PHPExcel_Calculation_MathTrig::FLOOR + GCD PHPExcel_Calculation_MathTrig::GCD + INT PHPExcel_Calculation_MathTrig::INT + LCM PHPExcel_Calculation_MathTrig::LCM LN log - LOG PHPExcel_Calculation_Functions::LOG_BASE + LOG PHPExcel_Calculation_MathTrig::LOG_BASE LOG10 log10 - MDETERM PHPExcel_Calculation_Functions::MDETERM - MINVERSE PHPExcel_Calculation_Functions::MINVERSE - MMULT PHPExcel_Calculation_Functions::MMULT - MOD PHPExcel_Calculation_Functions::MOD - MROUND PHPExcel_Calculation_Functions::MROUND - MULTINOMIAL PHPExcel_Calculation_Functions::MULTINOMIAL - ODD PHPExcel_Calculation_Functions::ODD + MDETERM PHPExcel_Calculation_MathTrig::MDETERM + MINVERSE PHPExcel_Calculation_MathTrig::MINVERSE + MMULT PHPExcel_Calculation_MathTrig::MMULT + MOD PHPExcel_Calculation_MathTrig::MOD + MROUND PHPExcel_Calculation_MathTrig::MROUND + MULTINOMIAL PHPExcel_Calculation_MathTrig::MULTINOMIAL + ODD PHPExcel_Calculation_MathTrig::ODD PI pi - POWER PHPExcel_Calculation_Functions::POWER - PRODUCT PHPExcel_Calculation_Functions::PRODUCT - QUOTIENT PHPExcel_Calculation_Functions::QUOTIENT + POWER PHPExcel_Calculation_MathTrig::POWER + PRODUCT PHPExcel_Calculation_MathTrig::PRODUCT + QUOTIENT PHPExcel_Calculation_MathTrig::QUOTIENT RADIANS deg2rad - RAND PHPExcel_Calculation_Functions::RAND - RANDBETWEEN PHPExcel_Calculation_Functions::RAND - ROMAN PHPExcel_Calculation_Functions::ROMAN + RAND PHPExcel_Calculation_MathTrig::RAND + RANDBETWEEN PHPExcel_Calculation_MathTrig::RAND + ROMAN PHPExcel_Calculation_MathTrig::ROMAN ROUND round - ROUNDDOWN PHPExcel_Calculation_Functions::ROUNDDOWN - ROUNDUP PHPExcel_Calculation_Functions::ROUNDUP - SERIESSUM PHPExcel_Calculation_Functions::SERIESSUM - SIGN PHPExcel_Calculation_Functions::SIGN + ROUNDDOWN PHPExcel_Calculation_MathTrig::ROUNDDOWN + ROUNDUP PHPExcel_Calculation_MathTrig::ROUNDUP + SERIESSUM PHPExcel_Calculation_MathTrig::SERIESSUM + SIGN PHPExcel_Calculation_MathTrig::SIGN SIN sin SINH sinh SQRT sqrt - SQRTPI PHPExcel_Calculation_Functions::SQRTPI - SUBTOTAL PHPExcel_Calculation_Functions::SUBTOTAL - SUM PHPExcel_Calculation_Functions::SUM - SUMIF PHPExcel_Calculation_Functions::SUMIF + SQRTPI PHPExcel_Calculation_MathTrig::SQRTPI + SUBTOTAL PHPExcel_Calculation_MathTrig::SUBTOTAL + SUM PHPExcel_Calculation_MathTrig::SUM + SUMIF PHPExcel_Calculation_MathTrig::SUMIF SUMIFS *** Not yet Implemented - SUMPRODUCT PHPExcel_Calculation_Functions::SUMPRODUCT - SUMSQ PHPExcel_Calculation_Functions::SUMSQ - SUMX2MY2 PHPExcel_Calculation_Functions::SUMX2MY2 - SUMX2PY2 PHPExcel_Calculation_Functions::SUMX2PY2 - SUMXMY2 PHPExcel_Calculation_Functions::SUMXMY2 + SUMPRODUCT PHPExcel_Calculation_MathTrig::SUMPRODUCT + SUMSQ PHPExcel_Calculation_MathTrig::SUMSQ + SUMX2MY2 PHPExcel_Calculation_MathTrig::SUMX2MY2 + SUMX2PY2 PHPExcel_Calculation_MathTrig::SUMX2PY2 + SUMXMY2 PHPExcel_Calculation_MathTrig::SUMXMY2 TAN tan TANH tanh - TRUNC PHPExcel_Calculation_Functions::TRUNC + TRUNC PHPExcel_Calculation_MathTrig::TRUNC CATEGORY_STATISTICAL - AVEDEV PHPExcel_Calculation_Functions::AVEDEV - AVERAGE PHPExcel_Calculation_Functions::AVERAGE - AVERAGEA PHPExcel_Calculation_Functions::AVERAGEA - AVERAGEIF *** Not yet Implemented + AVEDEV PHPExcel_Calculation_Statistical::AVEDEV + AVERAGE PHPExcel_Calculation_Statistical::AVERAGE + AVERAGEA PHPExcel_Calculation_Statistical::AVERAGEA + AVERAGEIF PHPExcel_Calculation_Statistical::AVERAGEIF AVERAGEIFS *** Not yet Implemented - BETADIST PHPExcel_Calculation_Functions::BETADIST - BETAINV PHPExcel_Calculation_Functions::BETAINV - BINOMDIST PHPExcel_Calculation_Functions::BINOMDIST - CHIDIST PHPExcel_Calculation_Functions::CHIDIST - CHIINV PHPExcel_Calculation_Functions::CHIINV + BETADIST PHPExcel_Calculation_Statistical::BETADIST + BETAINV PHPExcel_Calculation_Statistical::BETAINV + BINOMDIST PHPExcel_Calculation_Statistical::BINOMDIST + CHIDIST PHPExcel_Calculation_Statistical::CHIDIST + CHIINV PHPExcel_Calculation_Statistical::CHIINV CHITEST *** Not yet Implemented - CONFIDENCE PHPExcel_Calculation_Functions::CONFIDENCE - CORREL PHPExcel_Calculation_Functions::CORREL - COUNT PHPExcel_Calculation_Functions::COUNT - COUNTA PHPExcel_Calculation_Functions::COUNTA - COUNTBLANK PHPExcel_Calculation_Functions::COUNTBLANK - COUNTIF PHPExcel_Calculation_Functions::COUNTIF + CONFIDENCE PHPExcel_Calculation_Statistical::CONFIDENCE + CORREL PHPExcel_Calculation_Statistical::CORREL + COUNT PHPExcel_Calculation_Statistical::COUNT + COUNTA PHPExcel_Calculation_Statistical::COUNTA + COUNTBLANK PHPExcel_Calculation_Statistical::COUNTBLANK + COUNTIF PHPExcel_Calculation_Statistical::COUNTIF COUNTIFS *** Not yet Implemented - COVAR PHPExcel_Calculation_Functions::COVAR - CRITBINOM PHPExcel_Calculation_Functions::CRITBINOM - DEVSQ PHPExcel_Calculation_Functions::DEVSQ - EXPONDIST PHPExcel_Calculation_Functions::EXPONDIST + COVAR PHPExcel_Calculation_Statistical::COVAR + CRITBINOM PHPExcel_Calculation_Statistical::CRITBINOM + DEVSQ PHPExcel_Calculation_Statistical::DEVSQ + EXPONDIST PHPExcel_Calculation_Statistical::EXPONDIST FDIST *** Not yet Implemented FINV *** Not yet Implemented - FISHER PHPExcel_Calculation_Functions::FISHER - FISHERINV PHPExcel_Calculation_Functions::FISHERINV - FORECAST PHPExcel_Calculation_Functions::FORECAST + FISHER PHPExcel_Calculation_Statistical::FISHER + FISHERINV PHPExcel_Calculation_Statistical::FISHERINV + FORECAST PHPExcel_Calculation_Statistical::FORECAST FREQUENCY *** Not yet Implemented FTEST *** Not yet Implemented - GAMMADIST PHPExcel_Calculation_Functions::GAMMADIST - GAMMAINV PHPExcel_Calculation_Functions::GAMMAINV - GAMMALN PHPExcel_Calculation_Functions::GAMMALN - GEOMEAN PHPExcel_Calculation_Functions::GEOMEAN - GROWTH PHPExcel_Calculation_Functions::GROWTH - HARMEAN PHPExcel_Calculation_Functions::HARMEAN - HYPGEOMDIST PHPExcel_Calculation_Functions::HYPGEOMDIST - INTERCEPT PHPExcel_Calculation_Functions::INTERCEPT - KURT PHPExcel_Calculation_Functions::KURT - LARGE PHPExcel_Calculation_Functions::LARGE - LINEST PHPExcel_Calculation_Functions::LINEST - LOGEST PHPExcel_Calculation_Functions::LOGEST - LOGINV PHPExcel_Calculation_Functions::LOGINV - LOGNORMDIST PHPExcel_Calculation_Functions::LOGNORMDIST - MAX PHPExcel_Calculation_Functions::MAX - MAXA PHPExcel_Calculation_Functions::MAXA - MAXIF *** Not yet Implemented - MEDIAN PHPExcel_Calculation_Functions::MEDIAN + GAMMADIST PHPExcel_Calculation_Statistical::GAMMADIST + GAMMAINV PHPExcel_Calculation_Statistical::GAMMAINV + GAMMALN PHPExcel_Calculation_Statistical::GAMMALN + GEOMEAN PHPExcel_Calculation_Statistical::GEOMEAN + GROWTH PHPExcel_Calculation_Statistical::GROWTH + HARMEAN PHPExcel_Calculation_Statistical::HARMEAN + HYPGEOMDIST PHPExcel_Calculation_Statistical::HYPGEOMDIST + INTERCEPT PHPExcel_Calculation_Statistical::INTERCEPT + KURT PHPExcel_Calculation_Statistical::KURT + LARGE PHPExcel_Calculation_Statistical::LARGE + LINEST PHPExcel_Calculation_Statistical::LINEST + LOGEST PHPExcel_Calculation_Statistical::LOGEST + LOGINV PHPExcel_Calculation_Statistical::LOGINV + LOGNORMDIST PHPExcel_Calculation_Statistical::LOGNORMDIST + MAX PHPExcel_Calculation_Statistical::MAX + MAXA PHPExcel_Calculation_Statistical::MAXA + MAXIF PHPExcel_Calculation_Statistical::MAXIF + MEDIAN PHPExcel_Calculation_Statistical::MEDIAN MEDIANIF *** Not yet Implemented - MIN PHPExcel_Calculation_Functions::MIN - MINA PHPExcel_Calculation_Functions::MINA - MINIF *** Not yet Implemented - MODE PHPExcel_Calculation_Functions::MODE - NEGBINOMDIST PHPExcel_Calculation_Functions::NEGBINOMDIST - NORMDIST PHPExcel_Calculation_Functions::NORMDIST - NORMINV PHPExcel_Calculation_Functions::NORMINV - NORMSDIST PHPExcel_Calculation_Functions::NORMSDIST - NORMSINV PHPExcel_Calculation_Functions::NORMSINV - PEARSON PHPExcel_Calculation_Functions::CORREL - PERCENTILE PHPExcel_Calculation_Functions::PERCENTILE - PERCENTRANK PHPExcel_Calculation_Functions::PERCENTRANK - PERMUT PHPExcel_Calculation_Functions::PERMUT - POISSON PHPExcel_Calculation_Functions::POISSON + MIN PHPExcel_Calculation_Statistical::MIN + MINA PHPExcel_Calculation_Statistical::MINA + MINIF PHPExcel_Calculation_Statistical::MINIF + MODE PHPExcel_Calculation_Statistical::MODE + NEGBINOMDIST PHPExcel_Calculation_Statistical::NEGBINOMDIST + NORMDIST PHPExcel_Calculation_Statistical::NORMDIST + NORMINV PHPExcel_Calculation_Statistical::NORMINV + NORMSDIST PHPExcel_Calculation_Statistical::NORMSDIST + NORMSINV PHPExcel_Calculation_Statistical::NORMSINV + PEARSON PHPExcel_Calculation_Statistical::CORREL + PERCENTILE PHPExcel_Calculation_Statistical::PERCENTILE + PERCENTRANK PHPExcel_Calculation_Statistical::PERCENTRANK + PERMUT PHPExcel_Calculation_Statistical::PERMUT + POISSON PHPExcel_Calculation_Statistical::POISSON PROB *** Not yet Implemented - QUARTILE PHPExcel_Calculation_Functions::QUARTILE - RANK PHPExcel_Calculation_Functions::RANK - RSQ PHPExcel_Calculation_Functions::RSQ - SKEW PHPExcel_Calculation_Functions::SKEW - SLOPE PHPExcel_Calculation_Functions::SLOPE - SMALL PHPExcel_Calculation_Functions::SMALL - STANDARDIZE PHPExcel_Calculation_Functions::STANDARDIZE - STDEV PHPExcel_Calculation_Functions::STDEV - STDEVA PHPExcel_Calculation_Functions::STDEVA - STDEVP PHPExcel_Calculation_Functions::STDEVP - STDEVPA PHPExcel_Calculation_Functions::STDEVPA - STEYX PHPExcel_Calculation_Functions::STEYX - TDIST PHPExcel_Calculation_Functions::TDIST - TINV PHPExcel_Calculation_Functions::TINV - TREND PHPExcel_Calculation_Functions::TREND - TRIMMEAN PHPExcel_Calculation_Functions::TRIMMEAN + QUARTILE PHPExcel_Calculation_Statistical::QUARTILE + RANK PHPExcel_Calculation_Statistical::RANK + RSQ PHPExcel_Calculation_Statistical::RSQ + SKEW PHPExcel_Calculation_Statistical::SKEW + SLOPE PHPExcel_Calculation_Statistical::SLOPE + SMALL PHPExcel_Calculation_Statistical::SMALL + STANDARDIZE PHPExcel_Calculation_Statistical::STANDARDIZE + STDEV PHPExcel_Calculation_Statistical::STDEV + STDEVA PHPExcel_Calculation_Statistical::STDEVA + STDEVP PHPExcel_Calculation_Statistical::STDEVP + STDEVPA PHPExcel_Calculation_Statistical::STDEVPA + STEYX PHPExcel_Calculation_Statistical::STEYX + TDIST PHPExcel_Calculation_Statistical::TDIST + TINV PHPExcel_Calculation_Statistical::TINV + TREND PHPExcel_Calculation_Statistical::TREND + TRIMMEAN PHPExcel_Calculation_Statistical::TRIMMEAN TTEST *** Not yet Implemented - VAR PHPExcel_Calculation_Functions::VARFunc - VARA PHPExcel_Calculation_Functions::VARA - VARP PHPExcel_Calculation_Functions::VARP - VARPA PHPExcel_Calculation_Functions::VARPA - WEIBULL PHPExcel_Calculation_Functions::WEIBULL - ZTEST PHPExcel_Calculation_Functions::ZTEST + VAR PHPExcel_Calculation_Statistical::VARFunc + VARA PHPExcel_Calculation_Statistical::VARA + VARP PHPExcel_Calculation_Statistical::VARP + VARPA PHPExcel_Calculation_Statistical::VARPA + WEIBULL PHPExcel_Calculation_Statistical::WEIBULL + ZTEST PHPExcel_Calculation_Statistical::ZTEST CATEGORY_TEXT_AND_DATA ASC *** Not yet Implemented BAHTTEXT *** Not yet Implemented - CHAR PHPExcel_Calculation_Functions::CHARACTER - CLEAN PHPExcel_Calculation_Functions::TRIMNONPRINTABLE - CODE PHPExcel_Calculation_Functions::ASCIICODE - CONCATENATE PHPExcel_Calculation_Functions::CONCATENATE - DOLLAR PHPExcel_Calculation_Functions::DOLLAR + CHAR PHPExcel_Calculation_TextData::CHARACTER + CLEAN PHPExcel_Calculation_TextData::TRIMNONPRINTABLE + CODE PHPExcel_Calculation_TextData::ASCIICODE + CONCATENATE PHPExcel_Calculation_TextData::CONCATENATE + DOLLAR PHPExcel_Calculation_TextData::DOLLAR EXACT *** Not yet Implemented - FIND PHPExcel_Calculation_Functions::SEARCHSENSITIVE - FINDB PHPExcel_Calculation_Functions::SEARCHSENSITIVE - FIXED PHPExcel_Calculation_Functions::FIXEDFORMAT + FIND PHPExcel_Calculation_TextData::SEARCHSENSITIVE + FINDB PHPExcel_Calculation_TextData::SEARCHSENSITIVE + FIXED PHPExcel_Calculation_TextData::FIXEDFORMAT JIS *** Not yet Implemented - LEFT PHPExcel_Calculation_Functions::LEFT - LEFTB PHPExcel_Calculation_Functions::LEFT - LEN PHPExcel_Calculation_Functions::STRINGLENGTH - LENB PHPExcel_Calculation_Functions::STRINGLENGTH - LOWER PHPExcel_Calculation_Functions::LOWERCASE - MID PHPExcel_Calculation_Functions::MID - MIDB PHPExcel_Calculation_Functions::MID + LEFT PHPExcel_Calculation_TextData::LEFT + LEFTB PHPExcel_Calculation_TextData::LEFT + LEN PHPExcel_Calculation_TextData::STRINGLENGTH + LENB PHPExcel_Calculation_TextData::STRINGLENGTH + LOWER PHPExcel_Calculation_TextData::LOWERCASE + MID PHPExcel_Calculation_TextData::MID + MIDB PHPExcel_Calculation_TextData::MID PHONETIC *** Not yet Implemented - PROPER PHPExcel_Calculation_Functions::PROPERCASE - REPLACE PHPExcel_Calculation_Functions::REPLACE - REPLACEB PHPExcel_Calculation_Functions::REPLACE + PROPER PHPExcel_Calculation_TextData::PROPERCASE + REPLACE PHPExcel_Calculation_TextData::REPLACE + REPLACEB PHPExcel_Calculation_TextData::REPLACE REPT str_repeat - RIGHT PHPExcel_Calculation_Functions::RIGHT - RIGHTB PHPExcel_Calculation_Functions::RIGHT - SEARCH PHPExcel_Calculation_Functions::SEARCHINSENSITIVE - SEARCHB PHPExcel_Calculation_Functions::SEARCHINSENSITIVE - SUBSTITUTE PHPExcel_Calculation_Functions::SUBSTITUTE - T PHPExcel_Calculation_Functions::RETURNSTRING - TEXT PHPExcel_Calculation_Functions::TEXTFORMAT - TRIM PHPExcel_Calculation_Functions::TRIMSPACES - UPPER PHPExcel_Calculation_Functions::UPPERCASE + RIGHT PHPExcel_Calculation_TextData::RIGHT + RIGHTB PHPExcel_Calculation_TextData::RIGHT + SEARCH PHPExcel_Calculation_TextData::SEARCHINSENSITIVE + SEARCHB PHPExcel_Calculation_TextData::SEARCHINSENSITIVE + SUBSTITUTE PHPExcel_Calculation_TextData::SUBSTITUTE + T PHPExcel_Calculation_TextData::RETURNSTRING + TEXT PHPExcel_Calculation_TextData::TEXTFORMAT + TRIM PHPExcel_Calculation_TextData::TRIMSPACES + UPPER PHPExcel_Calculation_TextData::UPPERCASE VALUE *** Not yet Implemented diff --git a/Documentation/FunctionListByName.txt b/Documentation/FunctionListByName.txt index 746e6854..6b17edb0 100644 --- a/Documentation/FunctionListByName.txt +++ b/Documentation/FunctionListByName.txt @@ -1,69 +1,69 @@ ABS CATEGORY_MATH_AND_TRIG abs -ACCRINT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::ACCRINT -ACCRINTM CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::ACCRINTM +ACCRINT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::ACCRINT +ACCRINTM CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::ACCRINTM ACOS CATEGORY_MATH_AND_TRIG acos ACOSH CATEGORY_MATH_AND_TRIG acosh -ADDRESS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::CELL_ADDRESS -AMORDEGRC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::AMORDEGRC -AMORLINC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::AMORLINC -AND CATEGORY_LOGICAL PHPExcel_Calculation_Functions::LOGICAL_AND +ADDRESS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::CELL_ADDRESS +AMORDEGRC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::AMORDEGRC +AMORLINC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::AMORLINC +AND CATEGORY_LOGICAL PHPExcel_Calculation_Logical::LOGICAL_AND AREAS CATEGORY_LOOKUP_AND_REFERENCE *** Not yet Implemented ASC CATEGORY_TEXT_AND_DATA *** Not yet Implemented ASIN CATEGORY_MATH_AND_TRIG asin ASINH CATEGORY_MATH_AND_TRIG asinh ATAN CATEGORY_MATH_AND_TRIG atan -ATAN2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::REVERSE_ATAN2 +ATAN2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::REVERSE_ATAN2 ATANH CATEGORY_MATH_AND_TRIG atanh -AVEDEV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::AVEDEV -AVERAGE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::AVERAGE -AVERAGEA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::AVERAGEA -AVERAGEIF CATEGORY_STATISTICAL *** Not yet Implemented +AVEDEV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::AVEDEV +AVERAGE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::AVERAGE +AVERAGEA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::AVERAGEA +AVERAGEIF CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::AVERAGEIF AVERAGEIFS CATEGORY_STATISTICAL *** Not yet Implemented BAHTTEXT CATEGORY_TEXT_AND_DATA *** Not yet Implemented -BESSELI CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BESSELI -BESSELJ CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BESSELJ -BESSELK CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BESSELK -BESSELY CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BESSELY -BETADIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::BETADIST -BETAINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::BETAINV -BIN2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BINTODEC -BIN2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BINTOHEX -BIN2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::BINTOOCT -BINOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::BINOMDIST +BESSELI CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BESSELI +BESSELJ CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BESSELJ +BESSELK CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BESSELK +BESSELY CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BESSELY +BETADIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::BETADIST +BETAINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::BETAINV +BIN2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BINTODEC +BIN2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BINTOHEX +BIN2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::BINTOOCT +BINOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::BINOMDIST -CEILING CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::CEILING +CEILING CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::CEILING CELL CATEGORY_INFORMATION *** Not yet Implemented -CHAR CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::CHARACTER -CHIDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CHIDIST -CHIINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CHIINV +CHAR CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::CHARACTER +CHIDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CHIDIST +CHIINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CHIINV CHITEST CATEGORY_STATISTICAL *** Not yet Implemented -CHOOSE CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::CHOOSE -CLEAN CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::TRIMNONPRINTABLE -CODE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::ASCIICODE -COLUMN CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::COLUMN -COLUMNS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::COLUMNS -COMBIN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::COMBIN -COMPLEX CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::COMPLEX -CONCATENATE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::CONCATENATE -CONFIDENCE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CONFIDENCE -CONVERT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::CONVERTUOM -CORREL CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CORREL +CHOOSE CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::CHOOSE +CLEAN CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::TRIMNONPRINTABLE +CODE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::ASCIICODE +COLUMN CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::COLUMN +COLUMNS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::COLUMNS +COMBIN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::COMBIN +COMPLEX CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::COMPLEX +CONCATENATE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::CONCATENATE +CONFIDENCE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CONFIDENCE +CONVERT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::CONVERTUOM +CORREL CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CORREL COS CATEGORY_MATH_AND_TRIG cos COSH CATEGORY_MATH_AND_TRIG cosh -COUNT CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::COUNT -COUNTA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::COUNTA -COUNTBLANK CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::COUNTBLANK -COUNTIF CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::COUNTIF +COUNT CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::COUNT +COUNTA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::COUNTA +COUNTBLANK CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::COUNTBLANK +COUNTIF CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::COUNTIF COUNTIFS CATEGORY_STATISTICAL *** Not yet Implemented -COUPDAYBS CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPDAYBS -COUPDAYS CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPDAYS -COUPDAYSNC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPDAYSNC -COUPNCD CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPNCD -COUPNUM CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPNUM -COUPPCD CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::COUPPCD -COVAR CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::COVAR -CRITBINOM CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CRITBINOM +COUPDAYBS CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPDAYBS +COUPDAYS CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPDAYS +COUPDAYSNC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPDAYSNC +COUPNCD CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPNCD +COUPNUM CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPNUM +COUPPCD CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::COUPPCD +COVAR CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::COVAR +CRITBINOM CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CRITBINOM CUBEKPIMEMBER CATEGORY_CUBE *** Not yet Implemented CUBEMEMBER CATEGORY_CUBE *** Not yet Implemented CUBEMEMBERPROPERTY CATEGORY_CUBE *** Not yet Implemented @@ -71,32 +71,32 @@ CUBERANKEDMEMBER CATEGORY_CUBE *** Not yet Implemented CUBESET CATEGORY_CUBE *** Not yet Implemented CUBESETCOUNT CATEGORY_CUBE *** Not yet Implemented CUBEVALUE CATEGORY_CUBE *** Not yet Implemented -CUMIPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::CUMIPMT -CUMPRINC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::CUMPRINC +CUMIPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::CUMIPMT +CUMPRINC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::CUMPRINC -DATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DATE -DATEDIF CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DATEDIF -DATEVALUE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DATEVALUE +DATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATE +DATEDIF CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATEDIF +DATEVALUE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATEVALUE DAVERAGE CATEGORY_DATABASE *** Not yet Implemented -DAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DAYOFMONTH -DAYS360 CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DAYS360 -DB CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::DB +DAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DAYOFMONTH +DAYS360 CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DAYS360 +DB CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DB DCOUNT CATEGORY_DATABASE *** Not yet Implemented DCOUNTA CATEGORY_DATABASE *** Not yet Implemented -DDB CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::DDB -DEC2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::DECTOBIN -DEC2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::DECTOHEX -DEC2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::DECTOOCT +DDB CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DDB +DEC2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DECTOBIN +DEC2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DECTOHEX +DEC2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DECTOOCT DEGREES CATEGORY_MATH_AND_TRIG rad2deg -DELTA CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::DELTA -DEVSQ CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::DEVSQ +DELTA CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::DELTA +DEVSQ CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::DEVSQ DGET CATEGORY_DATABASE *** Not yet Implemented -DISC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::DISC +DISC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DISC DMAX CATEGORY_DATABASE *** Not yet Implemented DMIN CATEGORY_DATABASE *** Not yet Implemented -DOLLAR CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::DOLLAR -DOLLARDE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::DOLLARDE -DOLLARFR CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::DOLLARFR +DOLLAR CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::DOLLAR +DOLLARDE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DOLLARDE +DOLLARFR CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::DOLLARFR DPRODUCT CATEGORY_DATABASE *** Not yet Implemented DSTDEV CATEGORY_DATABASE *** Not yet Implemented DSTDEVP CATEGORY_DATABASE *** Not yet Implemented @@ -105,79 +105,79 @@ DURATION CATEGORY_FINANCIAL *** Not yet Implemented DVAR CATEGORY_DATABASE *** Not yet Implemented DVARP CATEGORY_DATABASE *** Not yet Implemented -EDATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::EDATE -EFFECT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::EFFECT -EOMONTH CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::EOMONTH -ERF CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::ERF -ERFC CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::ERFC +EDATE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::EDATE +EFFECT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::EFFECT +EOMONTH CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::EOMONTH +ERF CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::ERF +ERFC CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::ERFC ERROR.TYPE CATEGORY_INFORMATION PHPExcel_Calculation_Functions::ERROR_TYPE -EVEN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::EVEN +EVEN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::EVEN EXACT CATEGORY_TEXT_AND_DATA *** Not yet Implemented EXP CATEGORY_MATH_AND_TRIG exp -EXPONDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::EXPONDIST +EXPONDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::EXPONDIST -FACT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::FACT -FACTDOUBLE CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::FACTDOUBLE -FALSE CATEGORY_LOGICAL PHPExcel_Calculation_Functions::LOGICAL_FALSE +FACT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::FACT +FACTDOUBLE CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::FACTDOUBLE +FALSE CATEGORY_LOGICAL PHPExcel_Calculation_Logical::FALSE FDIST CATEGORY_STATISTICAL *** Not yet Implemented -FIND CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::SEARCHSENSITIVE -FINDB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::SEARCHSENSITIVE +FIND CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::SEARCHSENSITIVE +FINDB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::SEARCHSENSITIVE FINV CATEGORY_STATISTICAL *** Not yet Implemented -FISHER CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::FISHER -FISHERINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::FISHERINV -FIXED CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::FIXEDFORMAT -FLOOR CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::FLOOR -FORECAST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::FORECAST +FISHER CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::FISHER +FISHERINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::FISHERINV +FIXED CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::FIXEDFORMAT +FLOOR CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::FLOOR +FORECAST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::FORECAST FREQUENCY CATEGORY_STATISTICAL *** Not yet Implemented FTEST CATEGORY_STATISTICAL *** Not yet Implemented -FV CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::FV -FVSCHEDULE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::FVSCHEDULE +FV CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::FV +FVSCHEDULE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::FVSCHEDULE -GAMMADIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::GAMMADIST -GAMMAINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::GAMMAINV -GAMMALN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::GAMMALN -GCD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::GCD -GEOMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::GEOMEAN -GESTEP CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::GESTEP +GAMMADIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::GAMMADIST +GAMMAINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::GAMMAINV +GAMMALN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::GAMMALN +GCD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::GCD +GEOMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::GEOMEAN +GESTEP CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::GESTEP GETPIVOTDATA CATEGORY_LOOKUP_AND_REFERENCE *** Not yet Implemented -GROWTH CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::GROWTH +GROWTH CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::GROWTH -HARMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::HARMEAN -HEX2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::HEXTOBIN -HEX2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::HEXTODEC -HEX2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::HEXTOOCT +HARMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::HARMEAN +HEX2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::HEXTOBIN +HEX2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::HEXTODEC +HEX2OCT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::HEXTOOCT HLOOKUP CATEGORY_LOOKUP_AND_REFERENCE *** Not yet Implemented -HOUR CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::HOUROFDAY -HYPERLINK CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::HYPERLINK -HYPGEOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::HYPGEOMDIST +HOUR CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::HOUROFDAY +HYPERLINK CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::HYPERLINK +HYPGEOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::HYPGEOMDIST -IF CATEGORY_LOGICAL PHPExcel_Calculation_Functions::STATEMENT_IF -IFERROR CATEGORY_LOGICAL PHPExcel_Calculation_Functions::STATEMENT_IFERROR -IMABS CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMABS -IMAGINARY CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMAGINARY -IMARGUMENT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMARGUMENT -IMCONJUGATE CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMCONJUGATE -IMCOS CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMCOS -IMDIV CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMDIV -IMEXP CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMEXP -IMLN CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMLN -IMLOG10 CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMLOG10 -IMLOG2 CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMLOG2 -IMPOWER CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMPOWER -IMPRODUCT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMPRODUCT -IMREAL CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMREAL -IMSIN CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMSIN -IMSQRT CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMSQRT -IMSUB CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMSUB -IMSUM CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::IMSUM -INDEX CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::INDEX -INDIRECT CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::INDIRECT +IF CATEGORY_LOGICAL PHPExcel_Calculation_Logical::STATEMENT_IF +IFERROR CATEGORY_LOGICAL PHPExcel_Calculation_Logical::IFERROR +IMABS CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMABS +IMAGINARY CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMAGINARY +IMARGUMENT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMARGUMENT +IMCONJUGATE CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMCONJUGATE +IMCOS CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMCOS +IMDIV CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMDIV +IMEXP CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMEXP +IMLN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMLN +IMLOG10 CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMLOG10 +IMLOG2 CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMLOG2 +IMPOWER CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMPOWER +IMPRODUCT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMPRODUCT +IMREAL CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMREAL +IMSIN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMSIN +IMSQRT CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMSQRT +IMSUB CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMSUB +IMSUM CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::IMSUM +INDEX CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::INDEX +INDIRECT CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::INDIRECT INFO CATEGORY_INFORMATION *** Not yet Implemented -INT CATEGORY_MATH_AND_TRIG intval -INTERCEPT CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::INTERCEPT -INTRATE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::INTRATE -IPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::IPMT -IRR CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::IRR +INT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::INT +INTERCEPT CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::INTERCEPT +INTRATE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::INTRATE +IPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::IPMT +IRR CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::IRR ISBLANK CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_BLANK ISERR CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_ERR ISERROR CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_ERROR @@ -187,195 +187,195 @@ ISNA CATEGORY_INFORMATION PHPExcel_Calculation_Fun ISNONTEXT CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_NONTEXT ISNUMBER CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_NUMBER ISODD CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_ODD -ISPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::ISPMT +ISPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::ISPMT ISREF CATEGORY_INFORMATION *** Not yet Implemented ISTEXT CATEGORY_INFORMATION PHPExcel_Calculation_Functions::IS_TEXT JIS CATEGORY_TEXT_AND_DATA *** Not yet Implemented -KURT CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::KURT +KURT CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::KURT -LARGE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::LARGE -LCM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::LCM -LEFT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::LEFT -LEFTB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::LEFT -LEN CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::STRINGLENGTH -LENB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::STRINGLENGTH -LINEST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::LINEST +LARGE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::LARGE +LCM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::LCM +LEFT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::LEFT +LEFTB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::LEFT +LEN CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::STRINGLENGTH +LENB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::STRINGLENGTH +LINEST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::LINEST LN CATEGORY_MATH_AND_TRIG log -LOG CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::LOG_BASE +LOG CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::LOG_BASE LOG10 CATEGORY_MATH_AND_TRIG log10 -LOGEST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::LOGEST -LOGINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::LOGINV -LOGNORMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::LOGNORMDIST -LOOKUP CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::LOOKUP -LOWER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::LOWERCASE +LOGEST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::LOGEST +LOGINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::LOGINV +LOGNORMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::LOGNORMDIST +LOOKUP CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::LOOKUP +LOWER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::LOWERCASE -MATCH CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::MATCH -MAX CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MAX -MAXA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MAXA -MAXIF CATEGORY_STATISTICAL *** Not yet Implemented -MDETERM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MDETERM +MATCH CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::MATCH +MAX CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MAX +MAXA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MAXA +MAXIF CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MAXIF +MDETERM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MDETERM MDURATION CATEGORY_FINANCIAL *** Not yet Implemented -MEDIAN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MEDIAN +MEDIAN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MEDIAN MEDIANIF CATEGORY_STATISTICAL *** Not yet Implemented -MID CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::MID -MIDB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::MID -MIN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MIN -MINA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MINA -MINIF CATEGORY_STATISTICAL *** Not yet Implemented -MINUTE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::MINUTEOFHOUR -MINVERSE CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MINVERSE -MIRR CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::MIRR -MMULT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MMULT -MOD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MOD -MODE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::MODE -MONTH CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::MONTHOFYEAR -MROUND CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MROUND -MULTINOMIAL CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::MULTINOMIAL +MID CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::MID +MIDB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::MID +MIN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MIN +MINA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MINA +MINIF CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MINIF +MINUTE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::MINUTEOFHOUR +MINVERSE CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MINVERSE +MIRR CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::MIRR +MMULT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MMULT +MOD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MOD +MODE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::MODE +MONTH CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::MONTHOFYEAR +MROUND CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MROUND +MULTINOMIAL CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::MULTINOMIAL N CATEGORY_INFORMATION PHPExcel_Calculation_Functions::N NA CATEGORY_INFORMATION PHPExcel_Calculation_Functions::NA -NEGBINOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::NEGBINOMDIST -NETWORKDAYS CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::NETWORKDAYS -NOMINAL CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::NOMINAL -NORMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::NORMDIST -NORMINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::NORMINV -NORMSDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::NORMSDIST -NORMSINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::NORMSINV -NOT CATEGORY_LOGICAL PHPExcel_Calculation_Functions::LOGICAL_NOT -NOW CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DATETIMENOW -NPER CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::NPER -NPV CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::NPV +NEGBINOMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::NEGBINOMDIST +NETWORKDAYS CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::NETWORKDAYS +NOMINAL CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::NOMINAL +NORMDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::NORMDIST +NORMINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::NORMINV +NORMSDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::NORMSDIST +NORMSINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::NORMSINV +NOT CATEGORY_LOGICAL PHPExcel_Calculation_Logical::NOT +NOW CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATETIMENOW +NPER CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::NPER +NPV CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::NPV -OCT2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::OCTTOBIN -OCT2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::OCTTODEC -OCT2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Functions::OCTTOHEX -ODD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::ODD +OCT2BIN CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::OCTTOBIN +OCT2DEC CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::OCTTODEC +OCT2HEX CATEGORY_ENGINEERING PHPExcel_Calculation_Engineering::OCTTOHEX +ODD CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::ODD ODDFPRICE CATEGORY_FINANCIAL *** Not yet Implemented ODDFYIELD CATEGORY_FINANCIAL *** Not yet Implemented ODDLPRICE CATEGORY_FINANCIAL *** Not yet Implemented ODDLYIELD CATEGORY_FINANCIAL *** Not yet Implemented -OFFSET CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::OFFSET -OR CATEGORY_LOGICAL PHPExcel_Calculation_Functions::LOGICAL_OR +OFFSET CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::OFFSET +OR CATEGORY_LOGICAL PHPExcel_Calculation_Logical::LOGICAL_OR -PEARSON CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::CORREL -PERCENTILE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::PERCENTILE -PERCENTRANK CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::PERCENTRANK -PERMUT CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::PERMUT +PEARSON CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::CORREL +PERCENTILE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::PERCENTILE +PERCENTRANK CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::PERCENTRANK +PERMUT CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::PERMUT PHONETIC CATEGORY_TEXT_AND_DATA *** Not yet Implemented PI CATEGORY_MATH_AND_TRIG pi -PMT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PMT -POISSON CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::POISSON -POWER CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::POWER -PPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PPMT -PRICE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PRICE -PRICEDISC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PRICEDISC -PRICEMAT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PRICEMAT +PMT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PMT +POISSON CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::POISSON +POWER CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::POWER +PPMT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PPMT +PRICE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PRICE +PRICEDISC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PRICEDISC +PRICEMAT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PRICEMAT PROB CATEGORY_STATISTICAL *** Not yet Implemented -PRODUCT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::PRODUCT -PROPER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::PROPERCASE -PV CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::PV +PRODUCT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::PRODUCT +PROPER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::PROPERCASE +PV CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::PV -QUARTILE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::QUARTILE -QUOTIENT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::QUOTIENT +QUARTILE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::QUARTILE +QUOTIENT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::QUOTIENT RADIANS CATEGORY_MATH_AND_TRIG deg2rad -RAND CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::RAND -RANDBETWEEN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::RAND -RANK CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::RANK -RATE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::RATE -RECEIVED CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::RECEIVED -REPLACE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::REPLACE -REPLACEB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::REPLACE +RAND CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::RAND +RANDBETWEEN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::RAND +RANK CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::RANK +RATE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::RATE +RECEIVED CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::RECEIVED +REPLACE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::REPLACE +REPLACEB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::REPLACE REPT CATEGORY_TEXT_AND_DATA str_repeat -RIGHT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::RIGHT -RIGHTB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::RIGHT -ROMAN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::ROMAN +RIGHT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::RIGHT +RIGHTB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::RIGHT +ROMAN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::ROMAN ROUND CATEGORY_MATH_AND_TRIG round -ROUNDDOWN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::ROUNDDOWN -ROUNDUP CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::ROUNDUP -ROW CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::ROW -ROWS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::ROWS -RSQ CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::RSQ +ROUNDDOWN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::ROUNDDOWN +ROUNDUP CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::ROUNDUP +ROW CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::ROW +ROWS CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::ROWS +RSQ CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::RSQ RTD CATEGORY_LOOKUP_AND_REFERENCE *** Not yet Implemented -SEARCH CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::SEARCHINSENSITIVE -SEARCHB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::SEARCHINSENSITIVE -SECOND CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::SECONDOFMINUTE -SERIESSUM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SERIESSUM -SIGN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SIGN +SEARCH CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::SEARCHINSENSITIVE +SEARCHB CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::SEARCHINSENSITIVE +SECOND CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::SECONDOFMINUTE +SERIESSUM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SERIESSUM +SIGN CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SIGN SIN CATEGORY_MATH_AND_TRIG sin SINH CATEGORY_MATH_AND_TRIG sinh -SKEW CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::SKEW -SLN CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::SLN -SLOPE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::SLOPE -SMALL CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::SMALL +SKEW CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::SKEW +SLN CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::SLN +SLOPE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::SLOPE +SMALL CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::SMALL SQRT CATEGORY_MATH_AND_TRIG sqrt -SQRTPI CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SQRTPI -STANDARDIZE CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STANDARDIZE -STDEV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STDEV -STDEVA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STDEVA -STDEVP CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STDEVP -STDEVPA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STDEVPA -STEYX CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::STEYX -SUBSTITUTE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::SUBSTITUTE -SUBTOTAL CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUBTOTAL -SUM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUM -SUMIF CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMIF +SQRTPI CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SQRTPI +STANDARDIZE CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STANDARDIZE +STDEV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STDEV +STDEVA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STDEVA +STDEVP CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STDEVP +STDEVPA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STDEVPA +STEYX CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::STEYX +SUBSTITUTE CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::SUBSTITUTE +SUBTOTAL CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUBTOTAL +SUM CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUM +SUMIF CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMIF SUMIFS CATEGORY_MATH_AND_TRIG *** Not yet Implemented -SUMPRODUCT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMPRODUCT -SUMSQ CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMSQ -SUMX2MY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMX2MY2 -SUMX2PY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMX2PY2 -SUMXMY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::SUMXMY2 -SYD CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::SYD +SUMPRODUCT CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMPRODUCT +SUMSQ CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMSQ +SUMX2MY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMX2MY2 +SUMX2PY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMX2PY2 +SUMXMY2 CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::SUMXMY2 +SYD CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::SYD -T CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::RETURNSTRING +T CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::RETURNSTRING TAN CATEGORY_MATH_AND_TRIG tan TANH CATEGORY_MATH_AND_TRIG tanh -TBILLEQ CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::TBILLEQ -TBILLPRICE CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::TBILLPRICE -TBILLYIELD CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::TBILLYIELD -TDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::TDIST -TEXT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::TEXTFORMAT -TIME CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::TIME -TIMEVALUE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::TIMEVALUE -TINV CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::TINV -TODAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DATENOW -TRANSPOSE CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::TRANSPOSE -TREND CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::TREND -TRIM CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::TRIMSPACES -TRIMMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::TRIMMEAN -TRUE CATEGORY_LOGICAL PHPExcel_Calculation_Functions::LOGICAL_TRUE -TRUNC CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_Functions::TRUNC +TBILLEQ CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::TBILLEQ +TBILLPRICE CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::TBILLPRICE +TBILLYIELD CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::TBILLYIELD +TDIST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::TDIST +TEXT CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::TEXTFORMAT +TIME CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::TIME +TIMEVALUE CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::TIMEVALUE +TINV CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::TINV +TODAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DATENOW +TRANSPOSE CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::TRANSPOSE +TREND CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::TREND +TRIM CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::TRIMSPACES +TRIMMEAN CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::TRIMMEAN +TRUE CATEGORY_LOGICAL PHPExcel_Calculation_Logical::TRUE +TRUNC CATEGORY_MATH_AND_TRIG PHPExcel_Calculation_MathTrig::TRUNC TTEST CATEGORY_STATISTICAL *** Not yet Implemented TYPE CATEGORY_INFORMATION PHPExcel_Calculation_Functions::TYPE -UPPER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_Functions::UPPERCASE +UPPER CATEGORY_TEXT_AND_DATA PHPExcel_Calculation_TextData::UPPERCASE USDOLLAR CATEGORY_FINANCIAL *** Not yet Implemented VALUE CATEGORY_TEXT_AND_DATA *** Not yet Implemented -VAR CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::VARFunc -VARA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::VARA -VARP CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::VARP -VARPA CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::VARPA +VAR CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::VARFunc +VARA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::VARA +VARP CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::VARP +VARPA CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::VARPA VDB CATEGORY_FINANCIAL *** Not yet Implemented VERSION CATEGORY_INFORMATION PHPExcel_Calculation_Functions::VERSION -VLOOKUP CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_Functions::VLOOKUP +VLOOKUP CATEGORY_LOOKUP_AND_REFERENCE PHPExcel_Calculation_LookupRef::VLOOKUP -WEEKDAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::DAYOFWEEK -WEEKNUM CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::WEEKOFYEAR -WEIBULL CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::WEIBULL -WORKDAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::WORKDAY +WEEKDAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::DAYOFWEEK +WEEKNUM CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::WEEKOFYEAR +WEIBULL CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::WEIBULL +WORKDAY CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::WORKDAY -XIRR CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::XIRR -XNPV CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::XNPV +XIRR CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::XIRR +XNPV CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::XNPV -YEAR CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::YEAR -YEARFRAC CATEGORY_DATE_AND_TIME PHPExcel_Calculation_Functions::YEARFRAC +YEAR CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::YEAR +YEARFRAC CATEGORY_DATE_AND_TIME PHPExcel_Calculation_DateTime::YEARFRAC YIELD CATEGORY_FINANCIAL *** Not yet Implemented -YIELDDISC CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::YIELDDISC -YIELDMAT CATEGORY_FINANCIAL PHPExcel_Calculation_Functions::YIELDMAT +YIELDDISC CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::YIELDDISC +YIELDMAT CATEGORY_FINANCIAL PHPExcel_Calculation_Financial::YIELDMAT -ZTEST CATEGORY_STATISTICAL PHPExcel_Calculation_Functions::ZTEST +ZTEST CATEGORY_STATISTICAL PHPExcel_Calculation_Statistical::ZTEST