$iLastValue)){
// error: list is not ordered correctly
//echo "error: list is not ordered correctly
";
return self::$_errorCodes['na'];
}
}
}
// **
// find the match
// **
// loop on the cells
for ($i=0; $i < sizeof($lookup_array); ++$i){
// if match_type is 0 <=> find the first value that is exactly equal to lookup_value
if ($match_type==0 && $lookup_array[$i]==$lookup_value){
// this is the exact match
return $i+1;
}
// if match_type is -1 <=> find the smallest value that is greater than or equal to lookup_value
if ($match_type==-1 && $lookup_array[$i] < $lookup_value){
if ($i<1){
// 1st cell was allready smaller than the lookup_value
break;
}
else
// the previous cell was the match
return $i;
}
// if match_type is 1 <=> find the largest value that is less than or equal to lookup_value
if ($match_type==1 && $lookup_array[$i] > $lookup_value){
if ($i<1){
// 1st cell was allready bigger than the lookup_value
break;
}
else
// the previous cell was the match
return $i;
}
}
// unsuccessful in finding a match, return #N/A error value
//echo "unsuccessful in finding a match
";
return self::$_errorCodes['na'];
} // function MATCH()
/**
* 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'];
}
$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()
/**
* 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) {
$firstColumn = array_shift(array_keys($a));
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) {
// 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 {
$firstRow = array_pop(array_keys($lookup_array));
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);
$lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]);
if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) {
$lookup_vector = self::TRANSPOSE($lookup_vector);
$lookupRows = count($lookup_vector);
$lookupColumns = count($lookup_vector[array_shift(array_keys($lookup_vector))]);
}
if (is_null($result_vector)) {
$result_vector = $lookup_vector;
}
$resultRows = count($result_vector);
$resultColumns = count($result_vector[array_shift(array_keys($result_vector))]);
if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) {
$result_vector = self::TRANSPOSE($result_vector);
$resultRows = count($result_vector);
$resultColumns = count($result_vector[array_shift(array_keys($result_vector))]);
}
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)) {
$key1 = $key2 = array_shift(array_keys($value));
$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
*
* @param array $array Array to be flattened
* @return array Flattened array
*/
public static function flattenArray($array) {
if (!is_array($array)) {
return (array) $array;
}
$arrayValues = array();
foreach ($array as $value) {
if (is_array($value)) {
foreach ($value as $val) {
if (is_array($val)) {
foreach ($val as $v) {
$arrayValues[] = $v;
}
} else {
$arrayValues[] = $val;
}
}
} else {
$arrayValues[] = $value;
}
}
return $arrayValues;
} // function flattenArray()
/**
* Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing
*
* @param array $array Array to be flattened
* @return array Flattened array
*/
public static function flattenArrayIndexed($array) {
if (!is_array($array)) {
return (array) $array;
}
$arrayValues = array();
foreach ($array as $k1 => $value) {
if (is_array($value)) {
foreach ($value as $k2 => $val) {
if (is_array($val)) {
foreach ($val as $k3 => $v) {
$arrayValues[$k1.'.'.$k2.'.'.$k3] = $v;
}
} else {
$arrayValues[$k1.'.'.$k2] = $val;
}
}
} else {
$arrayValues[$k1] = $value;
}
}
return $arrayValues;
} // function flattenArrayIndexed()
/**
* Convert an array to a single scalar value by extracting the first element
*
* @param mixed $value Array or scalar value
* @return mixed
*/
public static function flattenSingleValue($value = '') {
if (is_array($value)) {
return self::flattenSingleValue(array_pop($value));
}
return $value;
} // function flattenSingleValue()
} // class PHPExcel_Calculation_Functions
//
// There are a few mathematical functions that aren't available on all versions of PHP for all platforms
// These functions aren't available in Windows implementations of PHP prior to version 5.3.0
// So we test if they do exist for this version of PHP/operating platform; and if not we create them
//
if (!function_exists('acosh')) {
function acosh($x) {
return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2));
} // function acosh()
}
if (!function_exists('asinh')) {
function asinh($x) {
return log($x + sqrt(1 + $x * $x));
} // function asinh()
}
if (!function_exists('atanh')) {
function atanh($x) {
return (log(1 + $x) - log(1 - $x)) / 2;
} // function atanh()
}
if (!function_exists('money_format')) {
function money_format($format, $number) {
$regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?',
'(?:\.([0-9]+))?([in%])/'
);
$regex = implode('', $regex);
if (setlocale(LC_MONETARY, null) == '') {
setlocale(LC_MONETARY, '');
}
$locale = localeconv();
$number = floatval($number);
if (!preg_match($regex, $format, $fmatch)) {
trigger_error("No format specified or invalid format", E_USER_WARNING);
return $number;
}
$flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ',
'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+',
'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
'isleft' => preg_match('/\-/', $fmatch[1]) > 0
);
$width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
$left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
$right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
$conversion = $fmatch[5];
$positive = true;
if ($number < 0) {
$positive = false;
$number *= -1;
}
$letter = $positive ? 'p' : 'n';
$prefix = $suffix = $cprefix = $csuffix = $signal = '';
if (!$positive) {
$signal = $locale['negative_sign'];
switch (true) {
case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(':
$prefix = '(';
$suffix = ')';
break;
case $locale['n_sign_posn'] == 1:
$prefix = $signal;
break;
case $locale['n_sign_posn'] == 2:
$suffix = $signal;
break;
case $locale['n_sign_posn'] == 3:
$cprefix = $signal;
break;
case $locale['n_sign_posn'] == 4:
$csuffix = $signal;
break;
}
}
if (!$flags['nosimbol']) {
$currency = $cprefix;
$currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']);
$currency .= $csuffix;
$currency = iconv('ISO-8859-1','UTF-8',$currency);
} else {
$currency = '';
}
$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';
$number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] );
$number = explode($locale['mon_decimal_point'], $number);
$n = strlen($prefix) + strlen($currency);
if ($left > 0 && $left > $n) {
if ($flags['isleft']) {
$number[0] .= str_repeat($flags['fillchar'], $left - $n);
} else {
$number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0];
}
}
$number = implode($locale['mon_decimal_point'], $number);
if ($locale["{$letter}_cs_precedes"]) {
$number = $prefix . $currency . $space . $number . $suffix;
} else {
$number = $prefix . $number . $space . $currency . $suffix;
}
if ($width > 0) {
$number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT);
}
$format = str_replace($fmatch[0], $number, $format);
return $format;
} // function money_format()
}
//
// Strangely, PHP doesn't have a mb_str_replace multibyte function
// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set
//
if ((!function_exists('mb_str_replace')) &&
(function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) {
function mb_str_replace($search, $replace, $subject) {
if(is_array($subject)) {
$ret = array();
foreach($subject as $key => $val) {
$ret[$key] = mb_str_replace($search, $replace, $val);
}
return $ret;
}
foreach((array) $search as $key => $s) {
if($s == '') {
continue;
}
$r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : '');
$pos = mb_strpos($subject, $s, 0, 'UTF-8');
while($pos !== false) {
$subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8');
$pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8');
}
}
return $subject;
}
}
PHPExcel/Calculation/FormulaParser.php 0000666 00000053461 15016734321 0013724 0 ustar 00 <";
const OPERATORS_POSTFIX = "%";
/**
* Formula
*
* @var string
*/
private $_formula;
/**
* Tokens
*
* @var PHPExcel_Calculation_FormulaToken[]
*/
private $_tokens = array();
/**
* Create a new PHPExcel_Calculation_FormulaParser
*
* @param string $pFormula Formula to parse
* @throws Exception
*/
public function __construct($pFormula = '')
{
// Check parameters
if (is_null($pFormula)) {
throw new Exception("Invalid parameter passed: formula");
}
// Initialise values
$this->_formula = trim($pFormula);
// Parse!
$this->_parseToTokens();
}
/**
* Get Formula
*
* @return string
*/
public function getFormula() {
return $this->_formula;
}
/**
* Get Token
*
* @param int $pId Token id
* @return string
* @throws Exception
*/
public function getToken($pId = 0) {
if (isset($this->_tokens[$pId])) {
return $this->_tokens[$pId];
} else {
throw new Exception("Token with id $pId does not exist.");
}
}
/**
* Get Token count
*
* @return string
*/
public function getTokenCount() {
return count($this->_tokens);
}
/**
* Get Tokens
*
* @return PHPExcel_Calculation_FormulaToken[]
*/
public function getTokens() {
return $this->_tokens;
}
/**
* Parse to tokens
*/
private function _parseToTokens() {
// No attempt is made to verify formulas; assumes formulas are derived from Excel, where
// they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions.
// Check if the formula has a valid starting =
$formulaLength = strlen($this->_formula);
if ($formulaLength < 2 || $this->_formula{0} != '=') return;
// Helper variables
$tokens1 = $tokens2 = $stack = array();
$inString = $inPath = $inRange = $inError = false;
$token = $previousToken = $nextToken = null;
$index = 1;
$value = '';
$ERRORS = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A");
$COMPARATORS_MULTI = array(">=", "<=", "<>");
while ($index < $formulaLength) {
// state-dependent character evaluation (order is important)
// double-quoted strings
// embeds are doubled
// end marks token
if ($inString) {
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) {
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE;
++$index;
} else {
$inString = false;
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT);
$value = "";
}
} else {
$value .= $this->_formula{$index};
}
++$index;
continue;
}
// single-quoted strings (links)
// embeds are double
// end does not mark a token
if ($inPath) {
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) {
$value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE;
++$index;
} else {
$inPath = false;
}
} else {
$value .= $this->_formula{$index};
}
++$index;
continue;
}
// bracked strings (R1C1 range index or linked workbook name)
// no embeds (changed to "()" by Excel)
// end does not mark a token
if ($inRange) {
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) {
$inRange = false;
}
$value .= $this->_formula{$index};
++$index;
continue;
}
// error values
// end marks a token, determined from absolute list of values
if ($inError) {
$value .= $this->_formula{$index};
++$index;
if (in_array($value, $ERRORS)) {
$inError = false;
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR);
$value = "";
}
continue;
}
// scientific notation check
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->_formula{$index}) !== false) {
if (strlen($value) > 1) {
if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->_formula{$index}) != 0) {
$value .= $this->_formula{$index};
++$index;
continue;
}
}
}
// independent character evaluation (order not important)
// establish state-dependent character evaluations
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) {
if (strlen($value > 0)) { // unexpected
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
$value = "";
}
$inString = true;
++$index;
continue;
}
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) {
if (strlen($value) > 0) { // unexpected
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
$value = "";
}
$inPath = true;
++$index;
continue;
}
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) {
$inRange = true;
$value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN;
++$index;
continue;
}
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) {
if (strlen($value) > 0) { // unexpected
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
$value = "";
}
$inError = true;
$value .= PHPExcel_Calculation_FormulaParser::ERROR_START;
++$index;
continue;
}
// mark start and end of arrays and array rows
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) {
if (strlen($value) > 0) { // unexpected
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN);
$value = "";
}
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
$tokens1[] = $tmp;
$stack[] = clone $tmp;
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
$tokens1[] = $tmp;
$stack[] = clone $tmp;
++$index;
continue;
}
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::SEMICOLON) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tmp = array_pop($stack);
$tmp->setValue("");
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
$tokens1[] = $tmp;
$tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
$tokens1[] = $tmp;
$tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
$tokens1[] = $tmp;
$stack[] = clone $tmp;
++$index;
continue;
}
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tmp = array_pop($stack);
$tmp->setValue("");
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
$tokens1[] = $tmp;
$tmp = array_pop($stack);
$tmp->setValue("");
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
$tokens1[] = $tmp;
++$index;
continue;
}
// trim white-space
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE);
++$index;
while (($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) {
++$index;
}
continue;
}
// multi-character comparators
if (($index + 2) <= $formulaLength) {
if (in_array(substr($this->_formula, $index, 2), $COMPARATORS_MULTI)) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->_formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
$index += 2;
continue;
}
}
// standard infix operators
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->_formula{$index}) !== false) {
if (strlen($value) > 0) {
$tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX);
++$index;
continue;
}
// standard postfix operators (only one)
if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->_formula{$index}) !== false) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX);
++$index;
continue;
}
// start subexpression or function
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) {
if (strlen($value) > 0) {
$tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
$tokens1[] = $tmp;
$stack[] = clone $tmp;
$value = "";
} else {
$tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START);
$tokens1[] = $tmp;
$stack[] = clone $tmp;
}
++$index;
continue;
}
// function, subexpression, or array parameters, or operand unions
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::COMMA) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tmp = array_pop($stack);
$tmp->setValue("");
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
$stack[] = $tmp;
if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION);
} else {
$tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT);
}
++$index;
continue;
}
// stop subexpression
if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) {
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
$value = "";
}
$tmp = array_pop($stack);
$tmp->setValue("");
$tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP);
$tokens1[] = $tmp;
++$index;
continue;
}
// token accumulation
$value .= $this->_formula{$index};
++$index;
}
// dump remaining accumulation
if (strlen($value) > 0) {
$tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND);
}
// move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections
$tokenCount = count($tokens1);
for ($i = 0; $i < $tokenCount; ++$i) {
$token = $tokens1[$i];
if (isset($tokens1[$i - 1])) {
$previousToken = $tokens1[$i - 1];
} else {
$previousToken = null;
}
if (isset($tokens1[$i + 1])) {
$nextToken = $tokens1[$i + 1];
} else {
$nextToken = null;
}
if (is_null($token)) {
continue;
}
if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) {
$tokens2[] = $token;
continue;
}
if (is_null($previousToken)) {
continue;
}
if (! (
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
) ) {
continue;
}
if (is_null($nextToken)) {
continue;
}
if (! (
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
(($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) ||
($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
) ) {
continue;
}
$tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION);
}
// move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators
// to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names
$this->_tokens = array();
$tokenCount = count($tokens2);
for ($i = 0; $i < $tokenCount; ++$i) {
$token = $tokens2[$i];
if (isset($tokens2[$i - 1])) {
$previousToken = $tokens2[$i - 1];
} else {
$previousToken = null;
}
if (isset($tokens2[$i + 1])) {
$nextToken = $tokens2[$i + 1];
} else {
$nextToken = null;
}
if (is_null($token)) {
continue;
}
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") {
if ($i == 0) {
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
} else if (
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
) {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
} else {
$token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX);
}
$this->_tokens[] = $token;
continue;
}
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") {
if ($i == 0) {
continue;
} else if (
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
(($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) ||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) ||
($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND)
) {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
} else {
continue;
}
$this->_tokens[] = $token;
continue;
}
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
} else if ($token->getValue() == "&") {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION);
} else {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH);
}
$this->_tokens[] = $token;
continue;
}
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) {
if (!is_numeric($token->getValue())) {
if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL);
} else {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE);
}
} else {
$token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER);
}
$this->_tokens[] = $token;
continue;
}
if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) {
if (strlen($token->getValue() > 0)) {
if (substr($token->getValue(), 0, 1) == "@") {
$token->setValue(substr($token->getValue(), 1));
}
}
}
$this->_tokens[] = $token;
}
}
}
PHPExcel/Comment.php 0000666 00000014502 15016734321 0010277 0 ustar 00 _author = 'Author';
$this->_text = new PHPExcel_RichText();
$this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1');
}
/**
* Get Author
*
* @return string
*/
public function getAuthor() {
return $this->_author;
}
/**
* Set Author
*
* @param string $pValue
* @return PHPExcel_Comment
*/
public function setAuthor($pValue = '') {
$this->_author = $pValue;
return $this;
}
/**
* Get Rich text comment
*
* @return PHPExcel_RichText
*/
public function getText() {
return $this->_text;
}
/**
* Set Rich text comment
*
* @param PHPExcel_RichText $pValue
* @return PHPExcel_Comment
*/
public function setText(PHPExcel_RichText $pValue) {
$this->_text = $pValue;
return $this;
}
/**
* Get comment width (CSS style, i.e. XXpx or YYpt)
*
* @return string
*/
public function getWidth() {
return $this->_width;
}
/**
* Set comment width (CSS style, i.e. XXpx or YYpt)
*
* @param string $value
* @return PHPExcel_Comment
*/
public function setWidth($value = '96pt') {
$this->_width = $value;
return $this;
}
/**
* Get comment height (CSS style, i.e. XXpx or YYpt)
*
* @return string
*/
public function getHeight() {
return $this->_height;
}
/**
* Set comment height (CSS style, i.e. XXpx or YYpt)
*
* @param string $value
* @return PHPExcel_Comment
*/
public function setHeight($value = '55.5pt') {
$this->_height = $value;
return $this;
}
/**
* Get left margin (CSS style, i.e. XXpx or YYpt)
*
* @return string
*/
public function getMarginLeft() {
return $this->_marginLeft;
}
/**
* Set left margin (CSS style, i.e. XXpx or YYpt)
*
* @param string $value
* @return PHPExcel_Comment
*/
public function setMarginLeft($value = '59.25pt') {
$this->_marginLeft = $value;
return $this;
}
/**
* Get top margin (CSS style, i.e. XXpx or YYpt)
*
* @return string
*/
public function getMarginTop() {
return $this->_marginTop;
}
/**
* Set top margin (CSS style, i.e. XXpx or YYpt)
*
* @param string $value
* @return PHPExcel_Comment
*/
public function setMarginTop($value = '1.5pt') {
$this->_marginTop = $value;
return $this;
}
/**
* Is the comment visible by default?
*
* @return boolean
*/
public function getVisible() {
return $this->_visible;
}
/**
* Set comment default visibility
*
* @param boolean $value
* @return PHPExcel_Comment
*/
public function setVisible($value = false) {
$this->_visible = $value;
return $this;
}
/**
* Get fill color
*
* @return PHPExcel_Style_Color
*/
public function getFillColor() {
return $this->_fillColor;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode() {
return md5(
$this->_author
. $this->_text->getHashCode()
. $this->_width
. $this->_height
. $this->_marginLeft
. $this->_marginTop
. ($this->_visible ? 1 : 0)
. $this->_fillColor->getHashCode()
. __CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/WorksheetIterator.php 0000666 00000005336 15016734321 0012367 0 ustar 00 _subject = $subject;
}
/**
* Destructor
*/
public function __destruct() {
unset($this->_subject);
}
/**
* Rewind iterator
*/
public function rewind() {
$this->_position = 0;
}
/**
* Current PHPExcel_Worksheet
*
* @return PHPExcel_Worksheet
*/
public function current() {
return $this->_subject->getSheet($this->_position);
}
/**
* Current key
*
* @return int
*/
public function key() {
return $this->_position;
}
/**
* Next value
*/
public function next() {
++$this->_position;
}
/**
* More PHPExcel_Worksheet instances available?
*
* @return boolean
*/
public function valid() {
return $this->_position < $this->_subject->getSheetCount();
}
}
PHPExcel/IComparable.php 0000666 00000002443 15016734321 0011054 0 ustar 00 _lockRevision = false;
$this->_lockStructure = false;
$this->_lockWindows = false;
$this->_revisionsPassword = '';
$this->_workbookPassword = '';
}
/**
* Is some sort of dcument security enabled?
*
* @return boolean
*/
function isSecurityEnabled() {
return $this->_lockRevision ||
$this->_lockStructure ||
$this->_lockWindows;
}
/**
* Get LockRevision
*
* @return boolean
*/
function getLockRevision() {
return $this->_lockRevision;
}
/**
* Set LockRevision
*
* @param boolean $pValue
* @return PHPExcel_DocumentSecurity
*/
function setLockRevision($pValue = false) {
$this->_lockRevision = $pValue;
return $this;
}
/**
* Get LockStructure
*
* @return boolean
*/
function getLockStructure() {
return $this->_lockStructure;
}
/**
* Set LockStructure
*
* @param boolean $pValue
* @return PHPExcel_DocumentSecurity
*/
function setLockStructure($pValue = false) {
$this->_lockStructure = $pValue;
return $this;
}
/**
* Get LockWindows
*
* @return boolean
*/
function getLockWindows() {
return $this->_lockWindows;
}
/**
* Set LockWindows
*
* @param boolean $pValue
* @return PHPExcel_DocumentSecurity
*/
function setLockWindows($pValue = false) {
$this->_lockWindows = $pValue;
return $this;
}
/**
* Get RevisionsPassword (hashed)
*
* @return string
*/
function getRevisionsPassword() {
return $this->_revisionsPassword;
}
/**
* Set RevisionsPassword
*
* @param string $pValue
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
* @return PHPExcel_DocumentSecurity
*/
function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) {
if (!$pAlreadyHashed) {
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
}
$this->_revisionsPassword = $pValue;
return $this;
}
/**
* Get WorkbookPassword (hashed)
*
* @return string
*/
function getWorkbookPassword() {
return $this->_workbookPassword;
}
/**
* Set WorkbookPassword
*
* @param string $pValue
* @param boolean $pAlreadyHashed If the password has already been hashed, set this to true
* @return PHPExcel_DocumentSecurity
*/
function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) {
if (!$pAlreadyHashed) {
$pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue);
}
$this->_workbookPassword = $pValue;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/NamedRange.php 0000666 00000012354 15016734321 0010701 0 ustar 00 _worksheet)
*
* @var bool
*/
private $_localOnly;
/**
* Create a new NamedRange
*
* @param string $pName
* @param PHPExcel_Worksheet $pWorksheet
* @param string $pRange
* @param bool $pLocalOnly
*/
public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false)
{
// Validate data
if (is_null($pName) || is_null($pWorksheet)|| is_null($pRange)) {
throw new Exception('Parameters can not be null.');
}
// Set local members
$this->_name = $pName;
$this->_worksheet = $pWorksheet;
$this->_range = $pRange;
$this->_localOnly = $pLocalOnly;
}
/**
* Get name
*
* @return string
*/
public function getName() {
return $this->_name;
}
/**
* Set name
*
* @param string $value
* @return PHPExcel_NamedRange
*/
public function setName($value = null) {
if (!is_null($value)) {
// Old title
$oldTitle = $this->_name;
// Re-attach
if (!is_null($this->_worksheet)) {
$this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet);
}
$this->_name = $value;
if (!is_null($this->_worksheet)) {
$this->_worksheet->getParent()->addNamedRange($this);
}
// New title
$newTitle = $this->_name;
PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle);
}
return $this;
}
/**
* Get worksheet
*
* @return PHPExcel_Worksheet
*/
public function getWorksheet() {
return $this->_worksheet;
}
/**
* Set worksheet
*
* @param PHPExcel_Worksheet $value
* @return PHPExcel_NamedRange
*/
public function setWorksheet(PHPExcel_Worksheet $value = null) {
if (!is_null($value)) {
$this->_worksheet = $value;
}
return $this;
}
/**
* Get range
*
* @return string
*/
public function getRange() {
return $this->_range;
}
/**
* Set range
*
* @param string $value
* @return PHPExcel_NamedRange
*/
public function setRange($value = null) {
if (!is_null($value)) {
$this->_range = $value;
}
return $this;
}
/**
* Get localOnly
*
* @return bool
*/
public function getLocalOnly() {
return $this->_localOnly;
}
/**
* Set localOnly
*
* @param bool $value
* @return PHPExcel_NamedRange
*/
public function setLocalOnly($value = false) {
$this->_localOnly = $value;
return $this;
}
/**
* Resolve a named range to a regular cell range
*
* @param string $pNamedRange Named range
* @param PHPExcel_Worksheet $pSheet Worksheet
* @return PHPExcel_NamedRange
*/
public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) {
return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/IOFactory.php 0000666 00000014352 15016734321 0010537 0 ustar 00 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ),
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' )
);
/**
* Autoresolve classes
*
* @var array
*/
private static $_autoResolveClasses = array(
'Excel2007',
'Excel5',
'Excel2003XML',
'OOCalc',
'SYLK',
'Serialized',
'CSV',
);
/**
* Private constructor for PHPExcel_IOFactory
*/
private function __construct() { }
/**
* Get search locations
*
* @return array
*/
public static function getSearchLocations() {
return self::$_searchLocations;
}
/**
* Set search locations
*
* @param array $value
* @throws Exception
*/
public static function setSearchLocations($value) {
if (is_array($value)) {
self::$_searchLocations = $value;
} else {
throw new Exception('Invalid parameter passed.');
}
}
/**
* Add search location
*
* @param string $type Example: IWriter
* @param string $location Example: PHPExcel/Writer/{0}.php
* @param string $classname Example: PHPExcel_Writer_{0}
*/
public static function addSearchLocation($type = '', $location = '', $classname = '') {
self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname );
}
/**
* Create PHPExcel_Writer_IWriter
*
* @param PHPExcel $phpExcel
* @param string $writerType Example: Excel2007
* @return PHPExcel_Writer_IWriter
*/
public static function createWriter(PHPExcel $phpExcel, $writerType = '') {
// Search type
$searchType = 'IWriter';
// Include class
foreach (self::$_searchLocations as $searchLocation) {
if ($searchLocation['type'] == $searchType) {
$className = str_replace('{0}', $writerType, $searchLocation['class']);
$classFile = str_replace('{0}', $writerType, $searchLocation['path']);
if (!class_exists($className)) {
require_once PHPEXCEL_ROOT . $classFile;
}
$instance = new $className($phpExcel);
if (!is_null($instance)) {
return $instance;
}
}
}
// Nothing found...
throw new Exception("No $searchType found for type $writerType");
}
/**
* Create PHPExcel_Reader_IReader
*
* @param string $readerType Example: Excel2007
* @return PHPExcel_Reader_IReader
*/
public static function createReader($readerType = '') {
// Search type
$searchType = 'IReader';
// Include class
foreach (self::$_searchLocations as $searchLocation) {
if ($searchLocation['type'] == $searchType) {
$className = str_replace('{0}', $readerType, $searchLocation['class']);
$classFile = str_replace('{0}', $readerType, $searchLocation['path']);
if (!class_exists($className)) {
require_once PHPEXCEL_ROOT . $classFile;
}
$instance = new $className();
if (!is_null($instance)) {
return $instance;
}
}
}
// Nothing found...
throw new Exception("No $searchType found for type $readerType");
}
/**
* Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution
*
* @param string $pFileName
* @return PHPExcel
*/
public static function load($pFilename) {
$reader = self::createReaderForFile($pFilename);
return $reader->load($pFilename);
}
/**
* Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution
*
* @param string $pFileName
* @return PHPExcel_Reader_IReader
*/
public static function createReaderForFile($pFilename) {
// First, lucky guess by inspecting file extension
$pathinfo = pathinfo($pFilename);
if (isset($pathinfo['extension'])) {
switch (strtolower($pathinfo['extension'])) {
case 'xlsx':
$reader = self::createReader('Excel2007');
break;
case 'xls':
$reader = self::createReader('Excel5');
break;
case 'ods':
$reader = self::createReader('OOCalc');
break;
case 'slk':
$reader = self::createReader('SYLK');
break;
case 'xml':
$reader = self::createReader('Excel2003XML');
break;
case 'csv':
// Do nothing
// We must not try to use CSV reader since it loads
// all files including Excel files etc.
break;
default:
break;
}
// Let's see if we are lucky
if ($reader->canRead($pFilename)) {
return $reader;
}
}
// If we reach here then "lucky guess" didn't give any result
// Try loading using self::$_autoResolveClasses
foreach (self::$_autoResolveClasses as $autoResolveClass) {
$reader = self::createReader($autoResolveClass);
if ($reader->canRead($pFilename)) {
return $reader;
}
}
}
}
PHPExcel/Cell/Hyperlink.php 0000666 00000006424 15016734321 0011525 0 ustar 00 _url = $pUrl;
$this->_tooltip = $pTooltip;
// Set cell
$this->_parent = $pCell;
}
/**
* Get URL
*
* @return string
*/
public function getUrl() {
return $this->_url;
}
/**
* Set URL
*
* @param string $value
* @return PHPExcel_Cell_Hyperlink
*/
public function setUrl($value = '') {
$this->_url = $value;
return $this;
}
/**
* Get tooltip
*
* @return string
*/
public function getTooltip() {
return $this->_tooltip;
}
/**
* Set tooltip
*
* @param string $value
* @return PHPExcel_Cell_Hyperlink
*/
public function setTooltip($value = '') {
$this->_tooltip = $value;
return $this;
}
/**
* Is this hyperlink internal? (to another sheet)
*
* @return boolean
*/
public function isInternal() {
return strpos($this->_url, 'sheet://') !== false;
}
/**
* Get parent
*
* @return PHPExcel_Cell
*/
public function getParent() {
return $this->_parent;
}
/**
* Set Parent
*
* @param PHPExcel_Cell $value
* @return PHPExcel_Cell_Hyperlink
*/
public function setParent($value = null) {
$this->_parent = $value;
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode() {
return md5(
$this->_url
. $this->_tooltip
. $this->_parent->getCoordinate()
. __CLASS__
);
}
}
PHPExcel/Cell/AdvancedValueBinder.php 0000666 00000010257 15016734321 0013405 0 ustar 00 setValueExplicit( (float)str_replace('%', '', $value) / 100, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE );
return true;
}
// Check for time e.g. '9:45', '09:45'
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) {
list($h, $m) = explode(':', $value);
$days = $h / 24 + $m / 1440;
// Convert value to number
$cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 );
return true;
}
// Check for date
if (strtotime($value) !== false) {
// make sure we have UTC for the sake of strtotime
$saveTimeZone = date_default_timezone_get();
date_default_timezone_set('UTC');
// Convert value to Excel date
$cell->setValueExplicit( PHPExcel_Shared_Date::PHPToExcel(strtotime($value)), PHPExcel_Cell_DataType::TYPE_NUMERIC);
// Set style
$cell->getParent()->getStyle( $cell->getCoordinate() )->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2 );
// restore original value for timezone
date_default_timezone_set($saveTimeZone);
return true;
}
}
// Not bound yet? Use parent...
return parent::bindValue($cell, $value);
}
}
PHPExcel/Cell/DataValidation.php 0000666 00000023102 15016734321 0012434 0 ustar 00 _formula1 = '';
$this->_formula2 = '';
$this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE;
$this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP;
$this->_operator = '';
$this->_allowBlank = false;
$this->_showDropDown = false;
$this->_showInputMessage = false;
$this->_showErrorMessage = false;
$this->_errorTitle = '';
$this->_error = '';
$this->_promptTitle = '';
$this->_prompt = '';
// Set cell
$this->_parent = $pCell;
}
/**
* Get Formula 1
*
* @return string
*/
public function getFormula1() {
return $this->_formula1;
}
/**
* Set Formula 1
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setFormula1($value = '') {
$this->_formula1 = $value;
return $this;
}
/**
* Get Formula 2
*
* @return string
*/
public function getFormula2() {
return $this->_formula2;
}
/**
* Set Formula 2
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setFormula2($value = '') {
$this->_formula2 = $value;
return $this;
}
/**
* Get Type
*
* @return string
*/
public function getType() {
return $this->_type;
}
/**
* Set Type
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) {
$this->_type = $value;
return $this;
}
/**
* Get Error style
*
* @return string
*/
public function getErrorStyle() {
return $this->_errorStyle;
}
/**
* Set Error style
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) {
$this->_errorStyle = $value;
return $this;
}
/**
* Get Operator
*
* @return string
*/
public function getOperator() {
return $this->_operator;
}
/**
* Set Operator
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setOperator($value = '') {
$this->_operator = $value;
return $this;
}
/**
* Get Allow Blank
*
* @return boolean
*/
public function getAllowBlank() {
return $this->_allowBlank;
}
/**
* Set Allow Blank
*
* @param boolean $value
* @return PHPExcel_Cell_DataValidation
*/
public function setAllowBlank($value = false) {
$this->_allowBlank = $value;
return $this;
}
/**
* Get Show DropDown
*
* @return boolean
*/
public function getShowDropDown() {
return $this->_showDropDown;
}
/**
* Set Show DropDown
*
* @param boolean $value
* @return PHPExcel_Cell_DataValidation
*/
public function setShowDropDown($value = false) {
$this->_showDropDown = $value;
return $this;
}
/**
* Get Show InputMessage
*
* @return boolean
*/
public function getShowInputMessage() {
return $this->_showInputMessage;
}
/**
* Set Show InputMessage
*
* @param boolean $value
* @return PHPExcel_Cell_DataValidation
*/
public function setShowInputMessage($value = false) {
$this->_showInputMessage = $value;
return $this;
}
/**
* Get Show ErrorMessage
*
* @return boolean
*/
public function getShowErrorMessage() {
return $this->_showErrorMessage;
}
/**
* Set Show ErrorMessage
*
* @param boolean $value
* @return PHPExcel_Cell_DataValidation
*/
public function setShowErrorMessage($value = false) {
$this->_showErrorMessage = $value;
return $this;
}
/**
* Get Error title
*
* @return string
*/
public function getErrorTitle() {
return $this->_errorTitle;
}
/**
* Set Error title
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setErrorTitle($value = '') {
$this->_errorTitle = $value;
return $this;
}
/**
* Get Error
*
* @return string
*/
public function getError() {
return $this->_error;
}
/**
* Set Error
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setError($value = '') {
$this->_error = $value;
return $this;
}
/**
* Get Prompt title
*
* @return string
*/
public function getPromptTitle() {
return $this->_promptTitle;
}
/**
* Set Prompt title
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setPromptTitle($value = '') {
$this->_promptTitle = $value;
return $this;
}
/**
* Get Prompt
*
* @return string
*/
public function getPrompt() {
return $this->_prompt;
}
/**
* Set Prompt
*
* @param string $value
* @return PHPExcel_Cell_DataValidation
*/
public function setPrompt($value = '') {
$this->_prompt = $value;
return $this;
}
/**
* Get parent
*
* @return PHPExcel_Cell
*/
public function getParent() {
return $this->_parent;
}
/**
* Set Parent
*
* @param PHPExcel_Cell $value
* @return PHPExcel_Cell_DataValidation
*/
public function setParent($value = null) {
$this->_parent = $value;
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode() {
return md5(
$this->_formula1
. $this->_formula2
. $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE
. $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP
. $this->_operator
. ($this->_allowBlank ? 't' : 'f')
. ($this->_showDropDown ? 't' : 'f')
. ($this->_showInputMessage ? 't' : 'f')
. ($this->_showErrorMessage ? 't' : 'f')
. $this->_errorTitle
. $this->_error
. $this->_promptTitle
. $this->_prompt
. $this->_parent->getCoordinate()
. __CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
// unbind parent
$this->setParent(null);
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value) && $key != '_parent') {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/Cell/DataType.php 0000666 00000006463 15016734321 0011276 0 ustar 00 0, '#DIV/0!' => 1, '#VALUE!' => 2, '#REF!' => 3, '#NAME?' => 4, '#NUM!' => 5, '#N/A' => 6);
/**
* Get list of error codes
*
* @return array
*/
public static function getErrorCodes() {
return self::$_errorCodes;
}
/**
* DataType for value
*
* @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure
* @param mixed $pValue
* @return int
*/
public static function dataTypeForValue($pValue = null) {
return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue);
}
/**
* Check a string that it satisfies Excel requirements
*
* @param mixed Value to sanitize to an Excel string
* @return mixed Sanitized value
*/
public static function checkString($pValue = null)
{
if ($pValue instanceof PHPExcel_RichText) {
// TODO: Sanitize Rich-Text string (max. character count is 32,767)
return $pValue;
}
// string must never be longer than 32,767 characters, truncate if necessary
$pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767);
// we require that newline is represented as "\n" in core, not as "\r\n" or "\r"
$pValue = str_replace(array("\r\n", "\r"), "\n", $pValue);
return $pValue;
}
/**
* Check a value that it is a valid error code
*
* @param mixed Value to sanitize to an Excel error code
* @return string Sanitized value
*/
public static function checkErrorCode($pValue = null)
{
$pValue = (string)$pValue;
if ( !array_key_exists($pValue, self::$_errorCodes) ) {
$pValue = '#NULL!';
}
return $pValue;
}
}
PHPExcel/Cell/IValueBinder.php 0000666 00000003276 15016734321 0012073 0 ustar 00 setValueExplicit( $value, PHPExcel_Cell_DataType::dataTypeForValue($value) );
// Done!
return true;
}
/**
* DataType for value
*
* @param mixed $pValue
* @return int
*/
public static function dataTypeForValue($pValue = null) {
// Match the value against a few data types
if (is_null($pValue)) {
return PHPExcel_Cell_DataType::TYPE_NULL;
} elseif ($pValue === '') {
return PHPExcel_Cell_DataType::TYPE_STRING;
} elseif ($pValue instanceof PHPExcel_RichText) {
return PHPExcel_Cell_DataType::TYPE_STRING;
} elseif ($pValue{0} === '=') {
return PHPExcel_Cell_DataType::TYPE_FORMULA;
} elseif (is_bool($pValue)) {
return PHPExcel_Cell_DataType::TYPE_BOOL;
} elseif (is_float($pValue) || is_int($pValue)) {
return PHPExcel_Cell_DataType::TYPE_NUMERIC;
} elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) {
return PHPExcel_Cell_DataType::TYPE_NUMERIC;
} elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) {
return PHPExcel_Cell_DataType::TYPE_ERROR;
} else {
return PHPExcel_Cell_DataType::TYPE_STRING;
}
}
}
PHPExcel/Style.php 0000666 00000046445 15016734321 0010010 0 ustar 00 _isSupervisor = $isSupervisor;
// Initialise values
$this->_conditionalStyles = array();
$this->_font = new PHPExcel_Style_Font($isSupervisor);
$this->_fill = new PHPExcel_Style_Fill($isSupervisor);
$this->_borders = new PHPExcel_Style_Borders($isSupervisor);
$this->_alignment = new PHPExcel_Style_Alignment($isSupervisor);
$this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor);
$this->_protection = new PHPExcel_Style_Protection($isSupervisor);
// bind parent if we are a supervisor
if ($isSupervisor) {
$this->_font->bindParent($this);
$this->_fill->bindParent($this);
$this->_borders->bindParent($this);
$this->_alignment->bindParent($this);
$this->_numberFormat->bindParent($this);
$this->_protection->bindParent($this);
}
}
/**
* Bind parent. Only used for supervisor
*
* @param PHPExcel $parent
* @return PHPExcel_Style
*/
public function bindParent($parent)
{
$this->_parent = $parent;
return $this;
}
/**
* Is this a supervisor or a real style component?
*
* @return boolean
*/
public function getIsSupervisor()
{
return $this->_isSupervisor;
}
/**
* Get the shared style component for the currently active cell in currently active sheet.
* Only used for style supervisor
*
* @return PHPExcel_Style
*/
public function getSharedComponent()
{
$activeSheet = $this->getActiveSheet();
$selectedCell = $this->getActiveCell(); // e.g. 'A1'
if ($activeSheet->cellExists($selectedCell)) {
$cell = $activeSheet->getCell($selectedCell);
$xfIndex = $cell->getXfIndex();
} else {
$xfIndex = 0;
}
$activeStyle = $this->_parent->getCellXfByIndex($xfIndex);
return $activeStyle;
}
/**
* Get the currently active sheet. Only used for supervisor
*
* @return PHPExcel_Worksheet
*/
public function getActiveSheet()
{
return $this->_parent->getActiveSheet();
}
/**
* Get the currently active cell coordinate in currently active sheet.
* Only used for supervisor
*
* @return string E.g. 'A1'
*/
public function getSelectedCells()
{
return $this->_parent->getActiveSheet()->getSelectedCells();
}
/**
* Get the currently active cell coordinate in currently active sheet.
* Only used for supervisor
*
* @return string E.g. 'A1'
*/
public function getActiveCell()
{
return $this->_parent->getActiveSheet()->getActiveCell();
}
/**
* Get parent. Only used for style supervisor
*
* @return PHPExcel
*/
public function getParent()
{
return $this->_parent;
}
/**
* Apply styles from array
*
*
* $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray(
* array(
* 'font' => array(
* 'name' => 'Arial',
* 'bold' => true,
* 'italic' => false,
* 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE,
* 'strike' => false,
* 'color' => array(
* 'rgb' => '808080'
* )
* ),
* 'borders' => array(
* 'bottom' => array(
* 'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
* 'color' => array(
* 'rgb' => '808080'
* )
* ),
* 'top' => array(
* 'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
* 'color' => array(
* 'rgb' => '808080'
* )
* )
* )
* )
* );
*
*
* @param array $pStyles Array containing style information
* @param boolean $pAdvanced Advanced mode for setting borders.
* @throws Exception
* @return PHPExcel_Style
*/
public function applyFromArray($pStyles = null, $pAdvanced = true) {
if (is_array($pStyles)) {
if ($this->_isSupervisor) {
$pRange = $this->getSelectedCells();
// Uppercase coordinate
$pRange = strtoupper($pRange);
// Is it a cell range or a single cell?
$rangeA = '';
$rangeB = '';
if (strpos($pRange, ':') === false) {
$rangeA = $pRange;
$rangeB = $pRange;
} else {
list($rangeA, $rangeB) = explode(':', $pRange);
}
// Calculate range outer borders
$rangeStart = PHPExcel_Cell::coordinateFromString($rangeA);
$rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB);
// Translate column into index
$rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1;
$rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1;
// Make sure we can loop upwards on rows and columns
if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
$tmp = $rangeStart;
$rangeStart = $rangeEnd;
$rangeEnd = $tmp;
}
// ADVANCED MODE:
if ($pAdvanced && isset($pStyles['borders'])) {
// 'allborders' is a shorthand property for 'outline' and 'inside' and
// it applies to components that have not been set explicitly
if (isset($pStyles['borders']['allborders'])) {
foreach (array('outline', 'inside') as $component) {
if (!isset($pStyles['borders'][$component])) {
$pStyles['borders'][$component] = $pStyles['borders']['allborders'];
}
}
unset($pStyles['borders']['allborders']); // not needed any more
}
// 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left'
// it applies to components that have not been set explicitly
if (isset($pStyles['borders']['outline'])) {
foreach (array('top', 'right', 'bottom', 'left') as $component) {
if (!isset($pStyles['borders'][$component])) {
$pStyles['borders'][$component] = $pStyles['borders']['outline'];
}
}
unset($pStyles['borders']['outline']); // not needed any more
}
// 'inside' is a shorthand property for 'vertical' and 'horizontal'
// it applies to components that have not been set explicitly
if (isset($pStyles['borders']['inside'])) {
foreach (array('vertical', 'horizontal') as $component) {
if (!isset($pStyles['borders'][$component])) {
$pStyles['borders'][$component] = $pStyles['borders']['inside'];
}
}
unset($pStyles['borders']['inside']); // not needed any more
}
// width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
$xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3);
$yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3);
// loop through up to 3 x 3 = 9 regions
for ($x = 1; $x <= $xMax; ++$x) {
// start column index for region
$colStart = ($x == 3) ?
PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0])
: PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1);
// end column index for region
$colEnd = ($x == 1) ?
PHPExcel_Cell::stringFromColumnIndex($rangeStart[0])
: PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x);
for ($y = 1; $y <= $yMax; ++$y) {
// which edges are touching the region
$edges = array();
// are we at left edge
if ($x == 1) {
$edges[] = 'left';
}
// are we at right edge
if ($x == $xMax) {
$edges[] = 'right';
}
// are we at top edge?
if ($y == 1) {
$edges[] = 'top';
}
// are we at bottom edge?
if ($y == $yMax) {
$edges[] = 'bottom';
}
// start row index for region
$rowStart = ($y == 3) ?
$rangeEnd[1] : $rangeStart[1] + $y - 1;
// end row index for region
$rowEnd = ($y == 1) ?
$rangeStart[1] : $rangeEnd[1] - $yMax + $y;
// build range for region
$range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
// retrieve relevant style array for region
$regionStyles = $pStyles;
unset($regionStyles['borders']['inside']);
// what are the inner edges of the region when looking at the selection
$innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges );
// inner edges that are not touching the region should take the 'inside' border properties if they have been set
foreach ($innerEdges as $innerEdge) {
switch ($innerEdge) {
case 'top':
case 'bottom':
// should pick up 'horizontal' border property if set
if (isset($pStyles['borders']['horizontal'])) {
$regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal'];
} else {
unset($regionStyles['borders'][$innerEdge]);
}
break;
case 'left':
case 'right':
// should pick up 'vertical' border property if set
if (isset($pStyles['borders']['vertical'])) {
$regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical'];
} else {
unset($regionStyles['borders'][$innerEdge]);
}
break;
}
}
// apply region style to region by calling applyFromArray() in simple mode
$this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false);
}
}
return;
}
// SIMPLE MODE:
// Selection type, inspect
if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) {
$selectionType = 'COLUMN';
} else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) {
$selectionType = 'ROW';
} else {
$selectionType = 'CELL';
}
// First loop through columns, rows, or cells to find out which styles are affected by this operation
switch ($selectionType) {
case 'COLUMN':
$oldXfIndexes = array();
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
$oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
}
break;
case 'ROW':
$oldXfIndexes = array();
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) {
$oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style
} else {
$oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true;
}
}
break;
case 'CELL':
$oldXfIndexes = array();
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
$oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true;
}
}
break;
}
// clone each of the affected styles, apply the style arrray, and add the new styles to the workbook
$workbook = $this->getActiveSheet()->getParent();
foreach ($oldXfIndexes as $oldXfIndex => $dummy) {
$style = $workbook->getCellXfByIndex($oldXfIndex);
$newStyle = clone $style;
$newStyle->applyFromArray($pStyles);
if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) {
// there is already such cell Xf in our collection
$newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
} else {
// we don't have such a cell Xf, need to add
$workbook->addCellXf($newStyle);
$newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
}
}
// Loop through columns, rows, or cells again and update the XF index
switch ($selectionType) {
case 'COLUMN':
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
$columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col);
$oldXfIndex = $columnDimension->getXfIndex();
$columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
}
break;
case 'ROW':
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
$rowDimension = $this->getActiveSheet()->getRowDimension($row);
$oldXfIndex = $rowDimension->getXfIndex() === null ?
0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style
$rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
}
break;
case 'CELL':
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
$cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row);
$oldXfIndex = $cell->getXfIndex();
$cell->setXfIndex($newXfIndexes[$oldXfIndex]);
}
}
break;
}
} else {
// not a supervisor, just apply the style array directly on style object
if (array_key_exists('fill', $pStyles)) {
$this->getFill()->applyFromArray($pStyles['fill']);
}
if (array_key_exists('font', $pStyles)) {
$this->getFont()->applyFromArray($pStyles['font']);
}
if (array_key_exists('borders', $pStyles)) {
$this->getBorders()->applyFromArray($pStyles['borders']);
}
if (array_key_exists('alignment', $pStyles)) {
$this->getAlignment()->applyFromArray($pStyles['alignment']);
}
if (array_key_exists('numberformat', $pStyles)) {
$this->getNumberFormat()->applyFromArray($pStyles['numberformat']);
}
if (array_key_exists('protection', $pStyles)) {
$this->getProtection()->applyFromArray($pStyles['protection']);
}
}
} else {
throw new Exception("Invalid style array passed.");
}
return $this;
}
/**
* Get Fill
*
* @return PHPExcel_Style_Fill
*/
public function getFill() {
return $this->_fill;
}
/**
* Get Font
*
* @return PHPExcel_Style_Font
*/
public function getFont() {
return $this->_font;
}
/**
* Set font
*
* @param PHPExcel_Style_Font $font
* @return PHPExcel_Style
*/
public function setFont(PHPExcel_Style_Font $font)
{
$this->_font = $font;
return $this;
}
/**
* Get Borders
*
* @return PHPExcel_Style_Borders
*/
public function getBorders() {
return $this->_borders;
}
/**
* Get Alignment
*
* @return PHPExcel_Style_Alignment
*/
public function getAlignment() {
return $this->_alignment;
}
/**
* Get Number Format
*
* @return PHPExcel_Style_NumberFormat
*/
public function getNumberFormat() {
return $this->_numberFormat;
}
/**
* Get Conditional Styles. Only used on supervisor.
*
* @return PHPExcel_Style_Conditional[]
*/
public function getConditionalStyles() {
return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell());
}
/**
* Set Conditional Styles. Only used on supervisor.
*
* @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles
* @return PHPExcel_Style
*/
public function setConditionalStyles($pValue = null) {
if (is_array($pValue)) {
foreach (PHPExcel_Cell::extractAllCellReferencesInRange($this->getSelectedCells()) as $cellReference) {
$this->getActiveSheet()->setConditionalStyles($cellReference, $pValue);
}
}
return $this;
}
/**
* Get Protection
*
* @return PHPExcel_Style_Protection
*/
public function getProtection() {
return $this->_protection;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode() {
$hashConditionals = '';
foreach ($this->_conditionalStyles as $conditional) {
$hashConditionals .= $conditional->getHashCode();
}
return md5(
$this->getFill()->getHashCode()
. $this->getFont()->getHashCode()
. $this->getBorders()->getHashCode()
. $this->getAlignment()->getHashCode()
. $this->getNumberFormat()->getHashCode()
. $hashConditionals
. $this->getProtection()->getHashCode()
. __CLASS__
);
}
/**
* Get own index in style collection
*
* @return int
*/
public function getIndex()
{
return $this->_index;
}
/**
* Set own index in style collection
*
* @param int $pValue
*/
public function setIndex($pValue)
{
$this->_index = $pValue;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/DocumentProperties.php 0000666 00000014675 15016734321 0012543 0 ustar 00 _creator = 'Unknown Creator';
$this->_lastModifiedBy = $this->_creator;
$this->_created = time();
$this->_modified = time();
$this->_title = "Untitled Spreadsheet";
$this->_subject = '';
$this->_description = '';
$this->_keywords = '';
$this->_category = '';
$this->_company = 'Microsoft Corporation';
}
/**
* Get Creator
*
* @return string
*/
public function getCreator() {
return $this->_creator;
}
/**
* Set Creator
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setCreator($pValue = '') {
$this->_creator = $pValue;
return $this;
}
/**
* Get Last Modified By
*
* @return string
*/
public function getLastModifiedBy() {
return $this->_lastModifiedBy;
}
/**
* Set Last Modified By
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setLastModifiedBy($pValue = '') {
$this->_lastModifiedBy = $pValue;
return $this;
}
/**
* Get Created
*
* @return datetime
*/
public function getCreated() {
return $this->_created;
}
/**
* Set Created
*
* @param datetime $pValue
* @return PHPExcel_DocumentProperties
*/
public function setCreated($pValue = null) {
if (is_null($pValue)) {
$pValue = time();
}
$this->_created = $pValue;
return $this;
}
/**
* Get Modified
*
* @return datetime
*/
public function getModified() {
return $this->_modified;
}
/**
* Set Modified
*
* @param datetime $pValue
* @return PHPExcel_DocumentProperties
*/
public function setModified($pValue = null) {
if (is_null($pValue)) {
$pValue = time();
}
$this->_modified = $pValue;
return $this;
}
/**
* Get Title
*
* @return string
*/
public function getTitle() {
return $this->_title;
}
/**
* Set Title
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setTitle($pValue = '') {
$this->_title = $pValue;
return $this;
}
/**
* Get Description
*
* @return string
*/
public function getDescription() {
return $this->_description;
}
/**
* Set Description
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setDescription($pValue = '') {
$this->_description = $pValue;
return $this;
}
/**
* Get Subject
*
* @return string
*/
public function getSubject() {
return $this->_subject;
}
/**
* Set Subject
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setSubject($pValue = '') {
$this->_subject = $pValue;
return $this;
}
/**
* Get Keywords
*
* @return string
*/
public function getKeywords() {
return $this->_keywords;
}
/**
* Set Keywords
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setKeywords($pValue = '') {
$this->_keywords = $pValue;
return $this;
}
/**
* Get Category
*
* @return string
*/
public function getCategory() {
return $this->_category;
}
/**
* Set Category
*
* @param string $pValue
* @return PHPExcel_DocumentProperties
*/
public function setCategory($pValue = '') {
$this->_category = $pValue;
return $this;
}
/**
* Get Company
*
* @return string
*/
public function getCompany() {
return $this->_company;
}
/**
* Set Company
*
* @param string $pValue
* @return PHPPowerPoint_DocumentProperties
*/
public function setCompany($pValue = '') {
$this->_company = $pValue;
return $this;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/RichText.php 0000666 00000015343 15016734321 0010433 0 ustar 00 _richTextElements = array();
// Set parent?
if (!is_null($pCell)) {
// Set parent cell
$this->_parent = $pCell;
// Add cell text and style
if ($this->_parent->getValue() != "") {
$objRun = new PHPExcel_RichText_Run($this->_parent->getValue());
$objRun->setFont(clone $this->_parent->getParent()->getStyle($this->_parent->getCoordinate())->getFont());
$this->addText($objRun);
}
// Set parent value
$this->_parent->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING);
}
}
/**
* Add text
*
* @param PHPExcel_RichText_ITextElement $pText Rich text element
* @throws Exception
* @return PHPExcel_RichText
*/
public function addText(PHPExcel_RichText_ITextElement $pText = null)
{
$this->_richTextElements[] = $pText;
return $this;
}
/**
* Create text
*
* @param string $pText Text
* @return PHPExcel_RichText_TextElement
* @throws Exception
*/
public function createText($pText = '')
{
$objText = new PHPExcel_RichText_TextElement($pText);
$this->addText($objText);
return $objText;
}
/**
* Create text run
*
* @param string $pText Text
* @return PHPExcel_RichText_Run
* @throws Exception
*/
public function createTextRun($pText = '')
{
$objText = new PHPExcel_RichText_Run($pText);
$this->addText($objText);
return $objText;
}
/**
* Get plain text
*
* @return string
*/
public function getPlainText()
{
// Return value
$returnValue = '';
// Loop through all PHPExcel_RichText_ITextElement
foreach ($this->_richTextElements as $text) {
$returnValue .= $text->getText();
}
// Return
return $returnValue;
}
/**
* Convert to string
*
* @return string
*/
public function __toString() {
return $this->getPlainText();
}
/**
* Get Rich Text elements
*
* @return PHPExcel_RichText_ITextElement[]
*/
public function getRichTextElements()
{
return $this->_richTextElements;
}
/**
* Set Rich Text elements
*
* @param PHPExcel_RichText_ITextElement[] $pElements Array of elements
* @throws Exception
* @return PHPExcel_RichText
*/
public function setRichTextElements($pElements = null)
{
if (is_array($pElements)) {
$this->_richTextElements = $pElements;
} else {
throw new Exception("Invalid PHPExcel_RichText_ITextElement[] array passed.");
}
return $this;
}
/**
* Get parent
*
* @return PHPExcel_Cell
*/
public function getParent() {
return $this->_parent;
}
/**
* Set parent
*
* @param PHPExcel_Cell $value
* @return PHPExcel_RichText
*/
public function setParent(PHPExcel_Cell $value) {
// Set parent
$this->_parent = $value;
// Set parent value
$this->_parent->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING);
// Verify style information
$sheet = $this->_parent->getParent();
$cellFont = $sheet->getStyle($this->_parent->getCoordinate())->getFont()->getSharedComponent();
foreach ($this->getRichTextElements() as $element) {
if (!($element instanceof PHPExcel_RichText_Run)) continue;
if ($element->getFont()->getHashCode() == $sheet->getDefaultStyle()->getFont()->getHashCode()) {
if ($element->getFont()->getHashCode() != $cellFont->getHashCode()) {
$element->setFont(clone $cellFont);
}
}
}
return $this;
}
/**
* Get hash code
*
* @return string Hash code
*/
public function getHashCode() {
$hashElements = '';
foreach ($this->_richTextElements as $element) {
$hashElements .= $element->getHashCode();
}
return md5(
$hashElements
. __CLASS__
);
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
$vars = get_object_vars($this);
foreach ($vars as $key => $value) {
if ($key == '_parent') continue;
if (is_object($value)) {
$this->$key = clone $value;
} else {
$this->$key = $value;
}
}
}
}
PHPExcel/Shared/OLERead.php 0000666 00000021153 15016734321 0011316 0 ustar 00 data = file_get_contents($sFileName);
// Check OLE identifier
if (substr($this->data, 0, 8) != self::IDENTIFIER_OLE) {
throw new Exception('The filename ' . $sFileName . ' is not recognised as an OLE file');
}
// Total number of sectors used for the SAT
$this->numBigBlockDepotBlocks = $this->_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
// SecID of the first sector of the directory stream
$this->rootStartBlock = $this->_GetInt4d($this->data, self::ROOT_START_BLOCK_POS);
// SecID of the first sector of the SSAT (or -2 if not extant)
$this->sbdStartBlock = $this->_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS);
// SecID of the first sector of the MSAT (or -2 if no additional sectors are used)
$this->extensionBlock = $this->_GetInt4d($this->data, self::EXTENSION_BLOCK_POS);
// Total number of sectors used by MSAT
$this->numExtensionBlocks = $this->_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS);
$bigBlockDepotBlocks = array();
$pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS;
$bbdBlocks = $this->numBigBlockDepotBlocks;
if ($this->numExtensionBlocks != 0) {
$bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
}
for ($i = 0; $i < $bbdBlocks; ++$i) {
$bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos);
$pos += 4;
}
for ($j = 0; $j < $this->numExtensionBlocks; ++$j) {
$pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE;
$blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1);
for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) {
$bigBlockDepotBlocks[$i] = $this->_GetInt4d($this->data, $pos);
$pos += 4;
}
$bbdBlocks += $blocksToRead;
if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
$this->extensionBlock = $this->_GetInt4d($this->data, $pos);
}
}
$pos = 0;
$index = 0;
$this->bigBlockChain = array();
for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) {
$pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE;
for ($j = 0 ; $j < self::BIG_BLOCK_SIZE / 4; ++$j) {
$this->bigBlockChain[$index] = $this->_GetInt4d($this->data, $pos);
$pos += 4 ;
++$index;
}
}
$pos = 0;
$index = 0;
$sbdBlock = $this->sbdStartBlock;
$this->smallBlockChain = array();
while ($sbdBlock != -2) {
$pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE;
for ($j = 0; $j < self::BIG_BLOCK_SIZE / 4; ++$j) {
$this->smallBlockChain[$index] = $this->_GetInt4d($this->data, $pos);
$pos += 4;
++$index;
}
$sbdBlock = $this->bigBlockChain[$sbdBlock];
}
$block = $this->rootStartBlock;
$pos = 0;
// read the directory stream
$this->entry = $this->_readData($block);
$this->_readPropertySets();
}
/**
* Extract binary stream data, workbook stream + sheet streams
*
* @return string
*/
public function getWorkBook()
{
if ($this->props[$this->wrkbook]['size'] < self::SMALL_BLOCK_THRESHOLD){
$rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']);
$streamData = '';
$block = $this->props[$this->wrkbook]['startBlock'];
$pos = 0;
while ($block != -2) {
$pos = $block * self::SMALL_BLOCK_SIZE;
$streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE);
$block = $this->smallBlockChain[$block];
}
return $streamData;
} else {
$numBlocks = $this->props[$this->wrkbook]['size'] / self::BIG_BLOCK_SIZE;
if ($this->props[$this->wrkbook]['size'] % self::BIG_BLOCK_SIZE != 0) {
++$numBlocks;
}
if ($numBlocks == 0) return '';
$streamData = '';
$block = $this->props[$this->wrkbook]['startBlock'];
$pos = 0;
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = $this->bigBlockChain[$block];
}
return $streamData;
}
}
/**
* Read a standard stream (by joining sectors using information from SAT)
*
* @param int $bl Sector ID where the stream starts
* @return string Data for standard stream
*/
private function _readData($bl)
{
$block = $bl;
$pos = 0;
$data = '';
while ($block != -2) {
$pos = ($block + 1) * self::BIG_BLOCK_SIZE;
$data = $data . substr($this->data, $pos, self::BIG_BLOCK_SIZE);
$block = $this->bigBlockChain[$block];
}
return $data;
}
/**
* Read entries in the directory stream.
*/
private function _readPropertySets()
{
$offset = 0;
// loop through entires, each entry is 128 bytes
while ($offset < strlen($this->entry)) {
// entry data (128 bytes)
$d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE);
// size in bytes of name
$nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8);
// type of entry
$type = ord($d[self::TYPE_POS]);
// sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook)
// sectorID of first sector of the short-stream container stream, if this entry is root entry
$startBlock = $this->_GetInt4d($d, self::START_BLOCK_POS);
$size = $this->_GetInt4d($d, self::SIZE_POS);
$name = '';
for ($i = 0; $i < $nameSize ; ++$i) {
$name .= $d[$i];
}
$name = str_replace("\x00", "", $name);
$this->props[] = array (
'name' => $name,
'type' => $type,
'startBlock' => $startBlock,
'size' => $size);
// Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook)
if (($name == 'Workbook') || ($name == 'Book') || ($name == 'WORKBOOK')) {
$this->wrkbook = count($this->props) - 1;
}
// Root entry
if ($name == 'Root Entry' || $name == 'ROOT ENTRY' || $name == 'R') {
$this->rootentry = count($this->props) - 1;
}
$offset += self::PROPERTY_STORAGE_BLOCK_SIZE;
}
}
/**
* Read 4 bytes of data at specified position
*
* @param string $data
* @param int $pos
* @return int
*/
private function _GetInt4d($data, $pos)
{
// Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems
$_or_24 = ord($data[$pos+3]);
if ($_or_24>=128) $_ord_24 = -abs((256-$_or_24) << 24);
else $_ord_24 = ($_or_24&127) << 24;
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $_ord_24;
}
}
PHPExcel/Shared/Escher.php 0000666 00000004272 15016734321 0011317 0 ustar 00 _dggContainer;
}
/**
* Set Drawing Group Container
*
* @param PHPExcel_Shared_Escher_DggContainer $dggContainer
*/
public function setDggContainer($dggContainer)
{
return $this->_dggContainer = $dggContainer;
}
/**
* Get Drawing Container
*
* @return PHPExcel_Shared_Escher_DgContainer
*/
public function getDgContainer()
{
return $this->_dgContainer;
}
/**
* Set Drawing Container
*
* @param PHPExcel_Shared_Escher_DgContainer $dgContainer
*/
public function setDgContainer($dgContainer)
{
return $this->_dgContainer = $dgContainer;
}
}
PHPExcel/Shared/JAMA/SingularValueDecomposition.php 0000666 00000031315 15016734321 0016132 0 ustar 00 = n, the singular value decomposition is
* an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
* an n-by-n orthogonal matrix V so that A = U*S*V'.
*
* The singular values, sigma[$k] = S[$k][$k], are ordered so that
* sigma[0] >= sigma[1] >= ... >= sigma[n-1].
*
* The singular value decompostion always exists, so the constructor will
* never fail. The matrix condition number and the effective numerical
* rank can be computed from this decomposition.
*
* @author Paul Meagher
* @license PHP v3.0
* @version 1.1
*/
class SingularValueDecomposition {
/**
* Internal storage of U.
* @var array
*/
private $U = array();
/**
* Internal storage of V.
* @var array
*/
private $V = array();
/**
* Internal storage of singular values.
* @var array
*/
private $s = array();
/**
* Row dimension.
* @var int
*/
private $m;
/**
* Column dimension.
* @var int
*/
private $n;
/**
* Construct the singular value decomposition
*
* Derived from LINPACK code.
*
* @param $A Rectangular matrix
* @return Structure to access U, S and V.
*/
public function __construct($Arg) {
// Initialize.
$A = $Arg->getArrayCopy();
$this->m = $Arg->getRowDimension();
$this->n = $Arg->getColumnDimension();
$nu = min($this->m, $this->n);
$e = array();
$work = array();
$wantu = true;
$wantv = true;
$nct = min($this->m - 1, $this->n);
$nrt = max(0, min($this->n - 2, $this->m));
// Reduce A to bidiagonal form, storing the diagonal elements
// in s and the super-diagonal elements in e.
for ($k = 0; $k < max($nct,$nrt); ++$k) {
if ($k < $nct) {
// Compute the transformation for the k-th column and
// place the k-th diagonal in s[$k].
// Compute 2-norm of k-th column without under/overflow.
$this->s[$k] = 0;
for ($i = $k; $i < $this->m; ++$i) {
$this->s[$k] = hypo($this->s[$k], $A[$i][$k]);
}
if ($this->s[$k] != 0.0) {
if ($A[$k][$k] < 0.0) {
$this->s[$k] = -$this->s[$k];
}
for ($i = $k; $i < $this->m; ++$i) {
$A[$i][$k] /= $this->s[$k];
}
$A[$k][$k] += 1.0;
}
$this->s[$k] = -$this->s[$k];
}
for ($j = $k + 1; $j < $this->n; ++$j) {
if (($k < $nct) & ($this->s[$k] != 0.0)) {
// Apply the transformation.
$t = 0;
for ($i = $k; $i < $this->m; ++$i) {
$t += $A[$i][$k] * $A[$i][$j];
}
$t = -$t / $A[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$A[$i][$j] += $t * $A[$i][$k];
}
// Place the k-th row of A into e for the
// subsequent calculation of the row transformation.
$e[$j] = $A[$k][$j];
}
}
if ($wantu AND ($k < $nct)) {
// Place the transformation in U for subsequent back
// multiplication.
for ($i = $k; $i < $this->m; ++$i) {
$this->U[$i][$k] = $A[$i][$k];
}
}
if ($k < $nrt) {
// Compute the k-th row transformation and place the
// k-th super-diagonal in e[$k].
// Compute 2-norm without under/overflow.
$e[$k] = 0;
for ($i = $k + 1; $i < $this->n; ++$i) {
$e[$k] = hypo($e[$k], $e[$i]);
}
if ($e[$k] != 0.0) {
if ($e[$k+1] < 0.0) {
$e[$k] = -$e[$k];
}
for ($i = $k + 1; $i < $this->n; ++$i) {
$e[$i] /= $e[$k];
}
$e[$k+1] += 1.0;
}
$e[$k] = -$e[$k];
if (($k+1 < $this->m) AND ($e[$k] != 0.0)) {
// Apply the transformation.
for ($i = $k+1; $i < $this->m; ++$i) {
$work[$i] = 0.0;
}
for ($j = $k+1; $j < $this->n; ++$j) {
for ($i = $k+1; $i < $this->m; ++$i) {
$work[$i] += $e[$j] * $A[$i][$j];
}
}
for ($j = $k + 1; $j < $this->n; ++$j) {
$t = -$e[$j] / $e[$k+1];
for ($i = $k + 1; $i < $this->m; ++$i) {
$A[$i][$j] += $t * $work[$i];
}
}
}
if ($wantv) {
// Place the transformation in V for subsequent
// back multiplication.
for ($i = $k + 1; $i < $this->n; ++$i) {
$this->V[$i][$k] = $e[$i];
}
}
}
}
// Set up the final bidiagonal matrix or order p.
$p = min($this->n, $this->m + 1);
if ($nct < $this->n) {
$this->s[$nct] = $A[$nct][$nct];
}
if ($this->m < $p) {
$this->s[$p-1] = 0.0;
}
if ($nrt + 1 < $p) {
$e[$nrt] = $A[$nrt][$p-1];
}
$e[$p-1] = 0.0;
// If required, generate U.
if ($wantu) {
for ($j = $nct; $j < $nu; ++$j) {
for ($i = 0; $i < $this->m; ++$i) {
$this->U[$i][$j] = 0.0;
}
$this->U[$j][$j] = 1.0;
}
for ($k = $nct - 1; $k >= 0; --$k) {
if ($this->s[$k] != 0.0) {
for ($j = $k + 1; $j < $nu; ++$j) {
$t = 0;
for ($i = $k; $i < $this->m; ++$i) {
$t += $this->U[$i][$k] * $this->U[$i][$j];
}
$t = -$t / $this->U[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->U[$i][$j] += $t * $this->U[$i][$k];
}
}
for ($i = $k; $i < $this->m; ++$i ) {
$this->U[$i][$k] = -$this->U[$i][$k];
}
$this->U[$k][$k] = 1.0 + $this->U[$k][$k];
for ($i = 0; $i < $k - 1; ++$i) {
$this->U[$i][$k] = 0.0;
}
} else {
for ($i = 0; $i < $this->m; ++$i) {
$this->U[$i][$k] = 0.0;
}
$this->U[$k][$k] = 1.0;
}
}
}
// If required, generate V.
if ($wantv) {
for ($k = $this->n - 1; $k >= 0; --$k) {
if (($k < $nrt) AND ($e[$k] != 0.0)) {
for ($j = $k + 1; $j < $nu; ++$j) {
$t = 0;
for ($i = $k + 1; $i < $this->n; ++$i) {
$t += $this->V[$i][$k]* $this->V[$i][$j];
}
$t = -$t / $this->V[$k+1][$k];
for ($i = $k + 1; $i < $this->n; ++$i) {
$this->V[$i][$j] += $t * $this->V[$i][$k];
}
}
}
for ($i = 0; $i < $this->n; ++$i) {
$this->V[$i][$k] = 0.0;
}
$this->V[$k][$k] = 1.0;
}
}
// Main iteration loop for the singular values.
$pp = $p - 1;
$iter = 0;
$eps = pow(2.0, -52.0);
while ($p > 0) {
// Here is where a test for too many iterations would go.
// This section of the program inspects for negligible
// elements in the s and e arrays. On completion the
// variables kase and k are set as follows:
// kase = 1 if s(p) and e[k-1] are negligible and k= -1; --$k) {
if ($k == -1) {
break;
}
if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) {
$e[$k] = 0.0;
break;
}
}
if ($k == $p - 2) {
$kase = 4;
} else {
for ($ks = $p - 1; $ks >= $k; --$ks) {
if ($ks == $k) {
break;
}
$t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.);
if (abs($this->s[$ks]) <= $eps * $t) {
$this->s[$ks] = 0.0;
break;
}
}
if ($ks == $k) {
$kase = 3;
} else if ($ks == $p-1) {
$kase = 1;
} else {
$kase = 2;
$k = $ks;
}
}
++$k;
// Perform the task indicated by kase.
switch ($kase) {
// Deflate negligible s(p).
case 1:
$f = $e[$p-2];
$e[$p-2] = 0.0;
for ($j = $p - 2; $j >= $k; --$j) {
$t = hypo($this->s[$j],$f);
$cs = $this->s[$j] / $t;
$sn = $f / $t;
$this->s[$j] = $t;
if ($j != $k) {
$f = -$sn * $e[$j-1];
$e[$j-1] = $cs * $e[$j-1];
}
if ($wantv) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1];
$this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1];
$this->V[$i][$j] = $t;
}
}
}
break;
// Split at negligible s(k).
case 2:
$f = $e[$k-1];
$e[$k-1] = 0.0;
for ($j = $k; $j < $p; ++$j) {
$t = hypo($this->s[$j], $f);
$cs = $this->s[$j] / $t;
$sn = $f / $t;
$this->s[$j] = $t;
$f = -$sn * $e[$j];
$e[$j] = $cs * $e[$j];
if ($wantu) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1];
$this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1];
$this->U[$i][$j] = $t;
}
}
}
break;
// Perform one qr step.
case 3:
// Calculate the shift.
$scale = max(max(max(max(
abs($this->s[$p-1]),abs($this->s[$p-2])),abs($e[$p-2])),
abs($this->s[$k])), abs($e[$k]));
$sp = $this->s[$p-1] / $scale;
$spm1 = $this->s[$p-2] / $scale;
$epm1 = $e[$p-2] / $scale;
$sk = $this->s[$k] / $scale;
$ek = $e[$k] / $scale;
$b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0;
$c = ($sp * $epm1) * ($sp * $epm1);
$shift = 0.0;
if (($b != 0.0) || ($c != 0.0)) {
$shift = sqrt($b * $b + $c);
if ($b < 0.0) {
$shift = -$shift;
}
$shift = $c / ($b + $shift);
}
$f = ($sk + $sp) * ($sk - $sp) + $shift;
$g = $sk * $ek;
// Chase zeros.
for ($j = $k; $j < $p-1; ++$j) {
$t = hypo($f,$g);
$cs = $f/$t;
$sn = $g/$t;
if ($j != $k) {
$e[$j-1] = $t;
}
$f = $cs * $this->s[$j] + $sn * $e[$j];
$e[$j] = $cs * $e[$j] - $sn * $this->s[$j];
$g = $sn * $this->s[$j+1];
$this->s[$j+1] = $cs * $this->s[$j+1];
if ($wantv) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1];
$this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1];
$this->V[$i][$j] = $t;
}
}
$t = hypo($f,$g);
$cs = $f/$t;
$sn = $g/$t;
$this->s[$j] = $t;
$f = $cs * $e[$j] + $sn * $this->s[$j+1];
$this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1];
$g = $sn * $e[$j+1];
$e[$j+1] = $cs * $e[$j+1];
if ($wantu && ($j < $this->m - 1)) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1];
$this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1];
$this->U[$i][$j] = $t;
}
}
}
$e[$p-2] = $f;
$iter = $iter + 1;
break;
// Convergence.
case 4:
// Make the singular values positive.
if ($this->s[$k] <= 0.0) {
$this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0);
if ($wantv) {
for ($i = 0; $i <= $pp; ++$i) {
$this->V[$i][$k] = -$this->V[$i][$k];
}
}
}
// Order the singular values.
while ($k < $pp) {
if ($this->s[$k] >= $this->s[$k+1]) {
break;
}
$t = $this->s[$k];
$this->s[$k] = $this->s[$k+1];
$this->s[$k+1] = $t;
if ($wantv AND ($k < $this->n - 1)) {
for ($i = 0; $i < $this->n; ++$i) {
$t = $this->V[$i][$k+1];
$this->V[$i][$k+1] = $this->V[$i][$k];
$this->V[$i][$k] = $t;
}
}
if ($wantu AND ($k < $this->m-1)) {
for ($i = 0; $i < $this->m; ++$i) {
$t = $this->U[$i][$k+1];
$this->U[$i][$k+1] = $this->U[$i][$k];
$this->U[$i][$k] = $t;
}
}
++$k;
}
$iter = 0;
--$p;
break;
} // end switch
} // end while
} // end constructor
/**
* Return the left singular vectors
*
* @access public
* @return U
*/
public function getU() {
return new Matrix($this->U, $this->m, min($this->m + 1, $this->n));
}
/**
* Return the right singular vectors
*
* @access public
* @return V
*/
public function getV() {
return new Matrix($this->V);
}
/**
* Return the one-dimensional array of singular values
*
* @access public
* @return diagonal of S.
*/
public function getSingularValues() {
return $this->s;
}
/**
* Return the diagonal matrix of singular values
*
* @access public
* @return S
*/
public function getS() {
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
$S[$i][$j] = 0.0;
}
$S[$i][$i] = $this->s[$i];
}
return new Matrix($S);
}
/**
* Two norm
*
* @access public
* @return max(S)
*/
public function norm2() {
return $this->s[0];
}
/**
* Two norm condition number
*
* @access public
* @return max(S)/min(S)
*/
public function cond() {
return $this->s[0] / $this->s[min($this->m, $this->n) - 1];
}
/**
* Effective numerical matrix rank
*
* @access public
* @return Number of nonnegligible singular values.
*/
public function rank() {
$eps = pow(2.0, -52.0);
$tol = max($this->m, $this->n) * $this->s[0] * $eps;
$r = 0;
for ($i = 0; $i < count($this->s); ++$i) {
if ($this->s[$i] > $tol) {
++$r;
}
}
return $r;
}
} // class SingularValueDecomposition
PHPExcel/Shared/JAMA/tests/TestMatrix.php 0000666 00000033213 15016734321 0014061 0 ustar 00 Testing constructors and constructor-like methods...
";
$A = new Matrix($columnwise, 3);
if($A instanceof Matrix) {
$this->try_success("Column-packed constructor...");
} else
$errorCount = $this->try_failure($errorCount, "Column-packed constructor...", "Unable to construct Matrix");
$T = new Matrix($tvals);
if($T instanceof Matrix)
$this->try_success("2D array constructor...");
else
$errorCount = $this->try_failure($errorCount, "2D array constructor...", "Unable to construct Matrix");
$A = new Matrix($columnwise, $validID);
$B = new Matrix($avals);
$tmp = $B->get(0,0);
$avals[0][0] = 0.0;
$C = $B->minus($A);
$avals[0][0] = $tmp;
$B = Matrix::constructWithCopy($avals);
$tmp = $B->get(0,0);
$avals[0][0] = 0.0;
/** check that constructWithCopy behaves properly **/
if ( ( $tmp - $B->get(0,0) ) != 0.0 )
$errorCount = $this->try_failure($errorCount,"constructWithCopy... ","copy not effected... data visible outside");
else
$this->try_success("constructWithCopy... ","");
$I = new Matrix($ivals);
if ( $this->checkMatrices($I,Matrix::identity(3,4)) )
$this->try_success("identity... ","");
else
$errorCount = $this->try_failure($errorCount,"identity... ","identity Matrix not successfully created");
/**
* Access Methods:
*
* getColumnDimension()
* getRowDimension()
* getArray()
* getArrayCopy()
* getColumnPackedCopy()
* getRowPackedCopy()
* get(int,int)
* getMatrix(int,int,int,int)
* getMatrix(int,int,int[])
* getMatrix(int[],int,int)
* getMatrix(int[],int[])
* set(int,int,double)
* setMatrix(int,int,int,int,Matrix)
* setMatrix(int,int,int[],Matrix)
* setMatrix(int[],int,int,Matrix)
* setMatrix(int[],int[],Matrix)
*/
print "Testing access methods...
";
$B = new Matrix($avals);
if($B->getRowDimension() == $rows)
$this->try_success("getRowDimension...");
else
$errorCount = $this->try_failure($errorCount, "getRowDimension...");
if($B->getColumnDimension() == $cols)
$this->try_success("getColumnDimension...");
else
$errorCount = $this->try_failure($errorCount, "getColumnDimension...");
$barray = $B->getArray();
if($this->checkArrays($barray, $avals))
$this->try_success("getArray...");
else
$errorCount = $this->try_failure($errorCount, "getArray...");
$bpacked = $B->getColumnPackedCopy();
if($this->checkArrays($bpacked, $columnwise))
$this->try_success("getColumnPackedCopy...");
else
$errorCount = $this->try_failure($errorCount, "getColumnPackedCopy...");
$bpacked = $B->getRowPackedCopy();
if($this->checkArrays($bpacked, $rowwise))
$this->try_success("getRowPackedCopy...");
else
$errorCount = $this->try_failure($errorCount, "getRowPackedCopy...");
/**
* Array-like methods:
* minus
* minusEquals
* plus
* plusEquals
* arrayLeftDivide
* arrayLeftDivideEquals
* arrayRightDivide
* arrayRightDivideEquals
* arrayTimes
* arrayTimesEquals
* uminus
*/
print "Testing array-like methods...
";
/**
* I/O methods:
* read
* print
* serializable:
* writeObject
* readObject
*/
print "Testing I/O methods...
";
/**
* Test linear algebra methods
*/
echo "Testing linear algebra methods...
";
$A = new Matrix($columnwise, 3);
if( $this->checkMatrices($A->transpose(), $T) )
$this->try_success("Transpose check...");
else
$errorCount = $this->try_failure($errorCount, "Transpose check...", "Matrices are not equal");
if($this->checkScalars($A->norm1(), $columnsummax))
$this->try_success("Maximum column sum...");
else
$errorCount = $this->try_failure($errorCount, "Maximum column sum...", "Incorrect: " . $A->norm1() . " != " . $columnsummax);
if($this->checkScalars($A->normInf(), $rowsummax))
$this->try_success("Maximum row sum...");
else
$errorCount = $this->try_failure($errorCount, "Maximum row sum...", "Incorrect: " . $A->normInf() . " != " . $rowsummax );
if($this->checkScalars($A->normF(), sqrt($sumofsquares)))
$this->try_success("Frobenius norm...");
else
$errorCount = $this->try_failure($errorCount, "Frobenius norm...", "Incorrect:" . $A->normF() . " != " . sqrt($sumofsquares));
if($this->checkScalars($A->trace(), $sumofdiagonals))
$this->try_success("Matrix trace...");
else
$errorCount = $this->try_failure($errorCount, "Matrix trace...", "Incorrect: " . $A->trace() . " != " . $sumofdiagonals);
$B = $A->getMatrix(0, $A->getRowDimension(), 0, $A->getRowDimension());
if( $B->det() == 0 )
$this->try_success("Matrix determinant...");
else
$errorCount = $this->try_failure($errorCount, "Matrix determinant...", "Incorrect: " . $B->det() . " != " . 0);
$A = new Matrix($columnwise,3);
$SQ = new Matrix($square);
if ($this->checkMatrices($SQ, $A->times($A->transpose())))
$this->try_success("times(Matrix)...");
else {
$errorCount = $this->try_failure($errorCount, "times(Matrix)...", "Unable to multiply matrices");
$SQ->toHTML();
$AT->toHTML();
}
$A = new Matrix($columnwise, 4);
$QR = $A->qr();
$R = $QR->getR();
$Q = $QR->getQ();
if($this->checkMatrices($A, $Q->times($R)))
$this->try_success("QRDecomposition...","");
else
$errorCount = $this->try_failure($errorCount,"QRDecomposition...","incorrect qr decomposition calculation");
$A = new Matrix($columnwise, 4);
$SVD = $A->svd();
$U = $SVD->getU();
$S = $SVD->getS();
$V = $SVD->getV();
if ($this->checkMatrices($A, $U->times($S->times($V->transpose()))))
$this->try_success("SingularValueDecomposition...","");
else
$errorCount = $this->try_failure($errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation");
$n = $A->getColumnDimension();
$A = $A->getMatrix(0,$n-1,0,$n-1);
$A->set(0,0,0.);
$LU = $A->lu();
$L = $LU->getL();
if ( $this->checkMatrices($A->getMatrix($LU->getPivot(),0,$n-1), $L->times($LU->getU())) )
$this->try_success("LUDecomposition...","");
else
$errorCount = $this->try_failure($errorCount,"LUDecomposition...","incorrect LU decomposition calculation");
$X = $A->inverse();
if ( $this->checkMatrices($A->times($X),Matrix::identity(3,3)) )
$this->try_success("inverse()...","");
else
$errorCount = $this->try_failure($errorCount, "inverse()...","incorrect inverse calculation");
$DEF = new Matrix($rankdef);
if($this->checkScalars($DEF->rank(), min($DEF->getRowDimension(), $DEF->getColumnDimension())-1))
$this->try_success("Rank...");
else
$this->try_failure("Rank...", "incorrect rank calculation");
$B = new Matrix($condmat);
$SVD = $B->svd();
$singularvalues = $SVD->getSingularValues();
if($this->checkScalars($B->cond(), $singularvalues[0]/$singularvalues[min($B->getRowDimension(), $B->getColumnDimension())-1]))
$this->try_success("Condition number...");
else
$this->try_failure("Condition number...", "incorrect condition number calculation");
$SUB = new Matrix($subavals);
$O = new Matrix($SUB->getRowDimension(),1,1.0);
$SOL = new Matrix($sqSolution);
$SQ = $SUB->getMatrix(0,$SUB->getRowDimension()-1,0,$SUB->getRowDimension()-1);
if ( $this->checkMatrices($SQ->solve($SOL),$O) )
$this->try_success("solve()...","");
else
$errorCount = $this->try_failure($errorCount,"solve()...","incorrect lu solve calculation");
$A = new Matrix($pvals);
$Chol = $A->chol();
$L = $Chol->getL();
if ( $this->checkMatrices($A, $L->times($L->transpose())) )
$this->try_success("CholeskyDecomposition...","");
else
$errorCount = $this->try_failure($errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation");
$X = $Chol->solve(Matrix::identity(3,3));
if ( $this->checkMatrices($A->times($X), Matrix::identity(3,3)) )
$this->try_success("CholeskyDecomposition solve()...","");
else
$errorCount = $this->try_failure($errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation");
$Eig = $A->eig();
$D = $Eig->getD();
$V = $Eig->getV();
if( $this->checkMatrices($A->times($V),$V->times($D)) )
$this->try_success("EigenvalueDecomposition (symmetric)...","");
else
$errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation");
$A = new Matrix($evals);
$Eig = $A->eig();
$D = $Eig->getD();
$V = $Eig->getV();
if ( $this->checkMatrices($A->times($V),$V->times($D)) )
$this->try_success("EigenvalueDecomposition (nonsymmetric)...","");
else
$errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation");
print("{$errorCount} total errors.");
}
/**
* Print appropriate messages for successful outcome try
* @param string $s
* @param string $e
*/
function try_success($s, $e = "") {
print "> ". $s ."success
";
if ($e != "")
print "> Message: ". $e ."
";
}
/**
* Print appropriate messages for unsuccessful outcome try
* @param int $count
* @param string $s
* @param string $e
* @return int incremented counter
*/
function try_failure($count, $s, $e="") {
print "> ". $s ."*** failure ***
> Message: ". $e ."
";
return ++$count;
}
/**
* Print appropriate messages for unsuccessful outcome try
* @param int $count
* @param string $s
* @param string $e
* @return int incremented counter
*/
function try_warning($count, $s, $e="") {
print "> ". $s ."*** warning ***
> Message: ". $e ."
";
return ++$count;
}
/**
* Check magnitude of difference of "scalars".
* @param float $x
* @param float $y
*/
function checkScalars($x, $y) {
$eps = pow(2.0,-52.0);
if ($x == 0 & abs($y) < 10*$eps) return;
if ($y == 0 & abs($x) < 10*$eps) return;
if (abs($x-$y) > 10 * $eps * max(abs($x),abs($y)))
return false;
else
return true;
}
/**
* Check norm of difference of "vectors".
* @param float $x[]
* @param float $y[]
*/
function checkVectors($x, $y) {
$nx = count($x);
$ny = count($y);
if ($nx == $ny)
for($i=0; $i < $nx; ++$i)
$this->checkScalars($x[$i],$y[$i]);
else
die("Attempt to compare vectors of different lengths");
}
/**
* Check norm of difference of "arrays".
* @param float $x[][]
* @param float $y[][]
*/
function checkArrays($x, $y) {
$A = new Matrix($x);
$B = new Matrix($y);
return $this->checkMatrices($A,$B);
}
/**
* Check norm of difference of "matrices".
* @param matrix $X
* @param matrix $Y
*/
function checkMatrices($X = null, $Y = null) {
if( $X == null || $Y == null )
return false;
$eps = pow(2.0,-52.0);
if ($X->norm1() == 0. & $Y->norm1() < 10*$eps) return true;
if ($Y->norm1() == 0. & $X->norm1() < 10*$eps) return true;
$A = $X->minus($Y);
if ($A->norm1() > 1000 * $eps * max($X->norm1(),$Y->norm1()))
die("The norm of (X-Y) is too large: ".$A->norm1());
else
return true;
}
}
$test = new TestMatrix;
?>
PHPExcel/Shared/JAMA/CHANGELOG.TXT 0000666 00000000764 15016734321 0011777 0 ustar 00 Mar 1, 2005 11:15 AST by PM
+ For consistency, renamed Math.php to Maths.java, utils to util,
tests to test, docs to doc -
+ Removed conditional logic from top of Matrix class.
+ Switched to using hypo function in Maths.php for all php-hypot calls.
NOTE TO SELF: Need to make sure that all decompositions have been
switched over to using the bundled hypo.
Feb 25, 2005 at 10:00 AST by PM
+ Recommend using simpler Error.php instead of JAMA_Error.php but
can be persuaded otherwise.
PHPExcel/Shared/JAMA/examples/MagicSquareExample.php 0000666 00000010617 15016734321 0016151 0 ustar 00 magic($p);
$M = array();
for ($j = 0; $j < $p; ++$j) {
for ($i = 0; $i < $p; ++$i) {
$aij = $A->get($i,$j);
$M[$i][$j] = $aij;
$M[$i][$j+$p] = $aij + 2*$p*$p;
$M[$i+$p][$j] = $aij + 3*$p*$p;
$M[$i+$p][$j+$p] = $aij + $p*$p;
}
}
for ($i = 0; $i < $p; ++$i) {
for ($j = 0; $j < $k; ++$j) {
$t = $M[$i][$j];
$M[$i][$j] = $M[$i+$p][$j];
$M[$i+$p][$j] = $t;
}
for ($j = $n-$k+1; $j < $n; ++$j) {
$t = $M[$i][$j];
$M[$i][$j] = $M[$i+$p][$j];
$M[$i+$p][$j] = $t;
}
}
$t = $M[$k][0]; $M[$k][0] = $M[$k+$p][0]; $M[$k+$p][0] = $t;
$t = $M[$k][$k]; $M[$k][$k] = $M[$k+$p][$k]; $M[$k+$p][$k] = $t;
}
return new Matrix($M);
}
/**
* Simple function to replicate PHP 5 behaviour
*/
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
/**
* Tests LU, QR, SVD and symmetric Eig decompositions.
*
* n = order of magic square.
* trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
* max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
* rank = linear algebraic rank, should equal n if n is odd,
* be less than n if n is even.
* cond = L_2 condition number, ratio of singular values.
* lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
* qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
*/
function main() {
?>
Test of Matrix Class, using magic squares.
See MagicSquareExample.main() for an explanation.
n |
trace |
max_eig |
rank |
cond |
lu_res |
qr_res |
microtime_float();
$eps = pow(2.0,-52.0);
for ($n = 3; $n <= 6; ++$n) {
echo "";
echo "$n | ";
$M = $this->magic($n);
$t = (int) $M->trace();
echo "$t | ";
$O = $M->plus($M->transpose());
$E = new EigenvalueDecomposition($O->times(0.5));
$d = $E->getRealEigenvalues();
echo "".$d[$n-1]." | ";
$r = $M->rank();
echo "".$r." | ";
$c = $M->cond();
if ($c < 1/$eps)
echo "".sprintf("%.3f",$c)." | ";
else
echo "Inf | ";
$LU = new LUDecomposition($M);
$L = $LU->getL();
$U = $LU->getU();
$p = $LU->getPivot();
// Java version: R = L.times(U).minus(M.getMatrix(p,0,n-1));
$S = $L->times($U);
$R = $S->minus($M->getMatrix($p,0,$n-1));
$res = $R->norm1()/($n*$eps);
echo "".sprintf("%.3f",$res)." | ";
$QR = new QRDecomposition($M);
$Q = $QR->getQ();
$R = $QR->getR();
$S = $Q->times($R);
$R = $S->minus($M);
$res = $R->norm1()/($n*$eps);
echo "".sprintf("%.3f",$res)." | ";
echo "
";
}
echo "";
echo "
";
$stop_time = $this->microtime_float();
$etime = $stop_time - $start_time;
echo "Elapsed time is ". sprintf("%.4f",$etime) ." seconds.
";
}
}
$magic = new MagicSquareExample();
$magic->main();
?>
PHPExcel/Shared/JAMA/examples/tile.php 0000666 00000002704 15016734321 0013367 0 ustar 00 getArray();
print_r($xArray);
$countRow = 0;
$countColumn = 0;
$m = $X->getRowDimension();
$n = $X->getColumnDimension();
if( $rowWise<1 || $colWise<1 ){
die("tile : Array index is out-of-bound.");
}
$newRowDim = $m*$rowWise;
$newColDim = $n*$colWise;
$result = array();
for($i=0 ; $i<$newRowDim; ++$i) {
$holder = array();
for($j=0 ; $j<$newColDim ; ++$j) {
$holder[$j] = $xArray[$countRow][$countColumn++];
// reset the column-index to zero to avoid reference to out-of-bound index in xArray[][]
if($countColumn == $n) { $countColumn = 0; }
} // end for
++$countRow;
// reset the row-index to zero to avoid reference to out-of-bound index in xArray[][]
if($countRow == $m) { $countRow = 0; }
$result[$i] = $holder;
} // end for
return new Matrix($result);
}
$X =array(1,2,3,4,5,6,7,8,9);
$nRow = 3;
$nCol = 3;
$tiled_matrix = tile(new Matrix($X), $nRow, $nCol);
echo "";
print_r($tiled_matrix);
echo "
";
?>
PHPExcel/Shared/JAMA/examples/Stats.php 0000666 00000154723 15016734321 0013541 0 ustar 00 |
// +----------------------------------------------------------------------+
//
// $Id: Stats.php,v 1.15 2003/06/01 11:40:30 jmcastagnetto Exp $
//
include_once 'PEAR.php';
/**
* @package Math_Stats
*/
// Constants for defining the statistics to calculate /*{{{*/
/**
* STATS_BASIC to generate the basic descriptive statistics
*/
define('STATS_BASIC', 1);
/**
* STATS_FULL to generate also higher moments, mode, median, etc.
*/
define('STATS_FULL', 2);
/*}}}*/
// Constants describing the data set format /*{{{*/
/**
* STATS_DATA_SIMPLE for an array of numeric values. This is the default.
* e.g. $data = array(2,3,4,5,1,1,6);
*/
define('STATS_DATA_SIMPLE', 0);
/**
* STATS_DATA_CUMMULATIVE for an associative array of frequency values,
* where in each array entry, the index is the data point and the
* value the count (frequency):
* e.g. $data = array(3=>4, 2.3=>5, 1.25=>6, 0.5=>3)
*/
define('STATS_DATA_CUMMULATIVE', 1);
/*}}}*/
// Constants defining how to handle nulls /*{{{*/
/**
* STATS_REJECT_NULL, reject data sets with null values. This is the default.
* Any non-numeric value is considered a null in this context.
*/
define('STATS_REJECT_NULL', -1);
/**
* STATS_IGNORE_NULL, ignore null values and prune them from the data.
* Any non-numeric value is considered a null in this context.
*/
define('STATS_IGNORE_NULL', -2);
/**
* STATS_USE_NULL_AS_ZERO, assign the value of 0 (zero) to null values.
* Any non-numeric value is considered a null in this context.
*/
define('STATS_USE_NULL_AS_ZERO', -3);
/*}}}*/
/**
* A class to calculate descriptive statistics from a data set.
* Data sets can be simple arrays of data, or a cummulative hash.
* The second form is useful when passing large data set,
* for example the data set:
*
*
* $data1 = array (1,2,1,1,1,1,3,3,4.1,3,2,2,4.1,1,1,2,3,3,2,2,1,1,2,2);
*
*
* can be epxressed more compactly as:
*
*
* $data2 = array('1'=>9, '2'=>8, '3'=>5, '4.1'=>2);
*
*
* Example of use:
*
*
* include_once 'Math/Stats.php';
* $s = new Math_Stats();
* $s->setData($data1);
* // or
* // $s->setData($data2, STATS_DATA_CUMMULATIVE);
* $stats = $s->calcBasic();
* echo 'Mean: '.$stats['mean'].' StDev: '.$stats['stdev'].'
\n';
*
* // using data with nulls
* // first ignoring them:
* $data3 = array(1.2, 'foo', 2.4, 3.1, 4.2, 3.2, null, 5.1, 6.2);
* $s->setNullOption(STATS_IGNORE_NULL);
* $s->setData($data3);
* $stats3 = $s->calcFull();
*
* // and then assuming nulls == 0
* $s->setNullOption(STATS_USE_NULL_AS_ZERO);
* $s->setData($data3);
* $stats3 = $s->calcFull();
*
*
* Originally this class was part of NumPHP (Numeric PHP package)
*
* @author Jesus M. Castagnetto
* @version 0.8
* @access public
* @package Math_Stats
*/
class Base {/*{{{*/
// properties /*{{{*/
/**
* The simple or cummulative data set.
* Null by default.
*
* @access private
* @var array
*/
var $_data = null;
/**
* Expanded data set. Only set when cummulative data
* is being used. Null by default.
*
* @access private
* @var array
*/
var $_dataExpanded = null;
/**
* Flag for data type, one of STATS_DATA_SIMPLE or
* STATS_DATA_CUMMULATIVE. Null by default.
*
* @access private
* @var int
*/
var $_dataOption = null;
/**
* Flag for null handling options. One of STATS_REJECT_NULL,
* STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO
*
* @access private
* @var int
*/
var $_nullOption;
/**
* Array for caching result values, should be reset
* when using setData()
*
* @access private
* @var array
*/
var $_calculatedValues = array();
/*}}}*/
/**
* Constructor for the class
*
* @access public
* @param optional int $nullOption how to handle null values
* @return object Math_Stats
*/
function Math_Stats($nullOption=STATS_REJECT_NULL) {/*{{{*/
$this->_nullOption = $nullOption;
}/*}}}*/
/**
* Sets and verifies the data, checking for nulls and using
* the current null handling option
*
* @access public
* @param array $arr the data set
* @param optional int $opt data format: STATS_DATA_CUMMULATIVE or STATS_DATA_SIMPLE (default)
* @return mixed true on success, a PEAR_Error object otherwise
*/
function setData($arr, $opt=STATS_DATA_SIMPLE) {/*{{{*/
if (!is_array($arr)) {
return PEAR::raiseError('invalid data, an array of numeric data was expected');
}
$this->_data = null;
$this->_dataExpanded = null;
$this->_dataOption = null;
$this->_calculatedValues = array();
if ($opt == STATS_DATA_SIMPLE) {
$this->_dataOption = $opt;
$this->_data = array_values($arr);
} else if ($opt == STATS_DATA_CUMMULATIVE) {
$this->_dataOption = $opt;
$this->_data = $arr;
$this->_dataExpanded = array();
}
return $this->_validate();
}/*}}}*/
/**
* Returns the data which might have been modified
* according to the current null handling options.
*
* @access public
* @param boolean $expanded whether to return a expanded list, default is false
* @return mixed array of data on success, a PEAR_Error object otherwise
* @see _validate()
*/
function getData($expanded=false) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if ($this->_dataOption == STATS_DATA_CUMMULATIVE && $expanded) {
return $this->_dataExpanded;
} else {
return $this->_data;
}
}/*}}}*/
/**
* Sets the null handling option.
* Must be called before assigning a new data set containing null values
*
* @access public
* @return mixed true on success, a PEAR_Error object otherwise
* @see _validate()
*/
function setNullOption($nullOption) {/*{{{*/
if ($nullOption == STATS_REJECT_NULL
|| $nullOption == STATS_IGNORE_NULL
|| $nullOption == STATS_USE_NULL_AS_ZERO) {
$this->_nullOption = $nullOption;
return true;
} else {
return PEAR::raiseError('invalid null handling option expecting: '.
'STATS_REJECT_NULL, STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO');
}
}/*}}}*/
/**
* Transforms the data by substracting each entry from the mean and
* dividing by its standard deviation. This will reset all pre-calculated
* values to their original (unset) defaults.
*
* @access public
* @return mixed true on success, a PEAR_Error object otherwise
* @see mean()
* @see stDev()
* @see setData()
*/
function studentize() {/*{{{*/
$mean = $this->mean();
if (PEAR::isError($mean)) {
return $mean;
}
$std = $this->stDev();
if (PEAR::isError($std)) {
return $std;
}
if ($std == 0) {
return PEAR::raiseError('cannot studentize data, standard deviation is zero.');
}
$arr = array();
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach ($this->_data as $val=>$freq) {
$newval = ($val - $mean) / $std;
$arr["$newval"] = $freq;
}
} else {
foreach ($this->_data as $val) {
$newval = ($val - $mean) / $std;
$arr[] = $newval;
}
}
return $this->setData($arr, $this->_dataOption);
}/*}}}*/
/**
* Transforms the data by substracting each entry from the mean.
* This will reset all pre-calculated values to their original (unset) defaults.
*
* @access public
* @return mixed true on success, a PEAR_Error object otherwise
* @see mean()
* @see setData()
*/
function center() {/*{{{*/
$mean = $this->mean();
if (PEAR::isError($mean)) {
return $mean;
}
$arr = array();
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach ($this->_data as $val=>$freq) {
$newval = $val - $mean;
$arr["$newval"] = $freq;
}
} else {
foreach ($this->_data as $val) {
$newval = $val - $mean;
$arr[] = $newval;
}
}
return $this->setData($arr, $this->_dataOption);
}/*}}}*/
/**
* Calculates the basic or full statistics for the data set
*
* @access public
* @param int $mode one of STATS_BASIC or STATS_FULL
* @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
* or only the error message will be returned (when false), if an error happens.
* @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
* @see calcBasic()
* @see calcFull()
*/
function calc($mode, $returnErrorObject=true) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if ($mode == STATS_BASIC) {
return $this->calcBasic($returnErrorObject);
} elseif ($mode == STATS_FULL) {
return $this->calcFull($returnErrorObject);
} else {
return PEAR::raiseError('incorrect mode, expected STATS_BASIC or STATS_FULL');
}
}/*}}}*/
/**
* Calculates a basic set of statistics
*
* @access public
* @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
* or only the error message will be returned (when false), if an error happens.
* @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
* @see calc()
* @see calcFull()
*/
function calcBasic($returnErrorObject=true) {/*{{{*/
return array (
'min' => $this->__format($this->min(), $returnErrorObject),
'max' => $this->__format($this->max(), $returnErrorObject),
'sum' => $this->__format($this->sum(), $returnErrorObject),
'sum2' => $this->__format($this->sum2(), $returnErrorObject),
'count' => $this->__format($this->count(), $returnErrorObject),
'mean' => $this->__format($this->mean(), $returnErrorObject),
'stdev' => $this->__format($this->stDev(), $returnErrorObject),
'variance' => $this->__format($this->variance(), $returnErrorObject),
'range' => $this->__format($this->range(), $returnErrorObject)
);
}/*}}}*/
/**
* Calculates a full set of statistics
*
* @access public
* @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
* or only the error message will be returned (when false), if an error happens.
* @return mixed an associative array of statistics on success, a PEAR_Error object otherwise
* @see calc()
* @see calcBasic()
*/
function calcFull($returnErrorObject=true) {/*{{{*/
return array (
'min' => $this->__format($this->min(), $returnErrorObject),
'max' => $this->__format($this->max(), $returnErrorObject),
'sum' => $this->__format($this->sum(), $returnErrorObject),
'sum2' => $this->__format($this->sum2(), $returnErrorObject),
'count' => $this->__format($this->count(), $returnErrorObject),
'mean' => $this->__format($this->mean(), $returnErrorObject),
'median' => $this->__format($this->median(), $returnErrorObject),
'mode' => $this->__format($this->mode(), $returnErrorObject),
'midrange' => $this->__format($this->midrange(), $returnErrorObject),
'geometric_mean' => $this->__format($this->geometricMean(), $returnErrorObject),
'harmonic_mean' => $this->__format($this->harmonicMean(), $returnErrorObject),
'stdev' => $this->__format($this->stDev(), $returnErrorObject),
'absdev' => $this->__format($this->absDev(), $returnErrorObject),
'variance' => $this->__format($this->variance(), $returnErrorObject),
'range' => $this->__format($this->range(), $returnErrorObject),
'std_error_of_mean' => $this->__format($this->stdErrorOfMean(), $returnErrorObject),
'skewness' => $this->__format($this->skewness(), $returnErrorObject),
'kurtosis' => $this->__format($this->kurtosis(), $returnErrorObject),
'coeff_of_variation' => $this->__format($this->coeffOfVariation(), $returnErrorObject),
'sample_central_moments' => array (
1 => $this->__format($this->sampleCentralMoment(1), $returnErrorObject),
2 => $this->__format($this->sampleCentralMoment(2), $returnErrorObject),
3 => $this->__format($this->sampleCentralMoment(3), $returnErrorObject),
4 => $this->__format($this->sampleCentralMoment(4), $returnErrorObject),
5 => $this->__format($this->sampleCentralMoment(5), $returnErrorObject)
),
'sample_raw_moments' => array (
1 => $this->__format($this->sampleRawMoment(1), $returnErrorObject),
2 => $this->__format($this->sampleRawMoment(2), $returnErrorObject),
3 => $this->__format($this->sampleRawMoment(3), $returnErrorObject),
4 => $this->__format($this->sampleRawMoment(4), $returnErrorObject),
5 => $this->__format($this->sampleRawMoment(5), $returnErrorObject)
),
'frequency' => $this->__format($this->frequency(), $returnErrorObject),
'quartiles' => $this->__format($this->quartiles(), $returnErrorObject),
'interquartile_range' => $this->__format($this->interquartileRange(), $returnErrorObject),
'interquartile_mean' => $this->__format($this->interquartileMean(), $returnErrorObject),
'quartile_deviation' => $this->__format($this->quartileDeviation(), $returnErrorObject),
'quartile_variation_coefficient' => $this->__format($this->quartileVariationCoefficient(), $returnErrorObject),
'quartile_skewness_coefficient' => $this->__format($this->quartileSkewnessCoefficient(), $returnErrorObject)
);
}/*}}}*/
/**
* Calculates the minimum of a data set.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the minimum value on success, a PEAR_Error object otherwise
* @see calc()
* @see max()
*/
function min() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('min', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$min = min(array_keys($this->_data));
} else {
$min = min($this->_data);
}
$this->_calculatedValues['min'] = $min;
}
return $this->_calculatedValues['min'];
}/*}}}*/
/**
* Calculates the maximum of a data set.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the maximum value on success, a PEAR_Error object otherwise
* @see calc()
* @see min()
*/
function max() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('max', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$max = max(array_keys($this->_data));
} else {
$max = max($this->_data);
}
$this->_calculatedValues['max'] = $max;
}
return $this->_calculatedValues['max'];
}/*}}}*/
/**
* Calculates SUM { xi }
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the sum on success, a PEAR_Error object otherwise
* @see calc()
* @see sum2()
* @see sumN()
*/
function sum() {/*{{{*/
if (!array_key_exists('sum', $this->_calculatedValues)) {
$sum = $this->sumN(1);
if (PEAR::isError($sum)) {
return $sum;
} else {
$this->_calculatedValues['sum'] = $sum;
}
}
return $this->_calculatedValues['sum'];
}/*}}}*/
/**
* Calculates SUM { (xi)^2 }
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the sum on success, a PEAR_Error object otherwise
* @see calc()
* @see sum()
* @see sumN()
*/
function sum2() {/*{{{*/
if (!array_key_exists('sum2', $this->_calculatedValues)) {
$sum2 = $this->sumN(2);
if (PEAR::isError($sum2)) {
return $sum2;
} else {
$this->_calculatedValues['sum2'] = $sum2;
}
}
return $this->_calculatedValues['sum2'];
}/*}}}*/
/**
* Calculates SUM { (xi)^n }
* Handles cummulative data sets correctly
*
* @access public
* @param numeric $n the exponent
* @return mixed the sum on success, a PEAR_Error object otherwise
* @see calc()
* @see sum()
* @see sum2()
*/
function sumN($n) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
$sumN = 0;
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach($this->_data as $val=>$freq) {
$sumN += $freq * pow((double)$val, (double)$n);
}
} else {
foreach($this->_data as $val) {
$sumN += pow((double)$val, (double)$n);
}
}
return $sumN;
}/*}}}*/
/**
* Calculates PROD { (xi) }, (the product of all observations)
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the product on success, a PEAR_Error object otherwise
* @see productN()
*/
function product() {/*{{{*/
if (!array_key_exists('product', $this->_calculatedValues)) {
$product = $this->productN(1);
if (PEAR::isError($product)) {
return $product;
} else {
$this->_calculatedValues['product'] = $product;
}
}
return $this->_calculatedValues['product'];
}/*}}}*/
/**
* Calculates PROD { (xi)^n }, which is the product of all observations
* Handles cummulative data sets correctly
*
* @access public
* @param numeric $n the exponent
* @return mixed the product on success, a PEAR_Error object otherwise
* @see product()
*/
function productN($n) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
$prodN = 1.0;
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach($this->_data as $val=>$freq) {
if ($val == 0) {
return 0.0;
}
$prodN *= $freq * pow((double)$val, (double)$n);
}
} else {
foreach($this->_data as $val) {
if ($val == 0) {
return 0.0;
}
$prodN *= pow((double)$val, (double)$n);
}
}
return $prodN;
}/*}}}*/
/**
* Calculates the number of data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the count on success, a PEAR_Error object otherwise
* @see calc()
*/
function count() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('count', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$count = count($this->_dataExpanded);
} else {
$count = count($this->_data);
}
$this->_calculatedValues['count'] = $count;
}
return $this->_calculatedValues['count'];
}/*}}}*/
/**
* Calculates the mean (average) of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the mean value on success, a PEAR_Error object otherwise
* @see calc()
* @see sum()
* @see count()
*/
function mean() {/*{{{*/
if (!array_key_exists('mean', $this->_calculatedValues)) {
$sum = $this->sum();
if (PEAR::isError($sum)) {
return $sum;
}
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$this->_calculatedValues['mean'] = $sum / $count;
}
return $this->_calculatedValues['mean'];
}/*}}}*/
/**
* Calculates the range of the data set = max - min
*
* @access public
* @return mixed the value of the range on success, a PEAR_Error object otherwise.
*/
function range() {/*{{{*/
if (!array_key_exists('range', $this->_calculatedValues)) {
$min = $this->min();
if (PEAR::isError($min)) {
return $min;
}
$max = $this->max();
if (PEAR::isError($max)) {
return $max;
}
$this->_calculatedValues['range'] = $max - $min;
}
return $this->_calculatedValues['range'];
}/*}}}*/
/**
* Calculates the variance (unbiased) of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the variance value on success, a PEAR_Error object otherwise
* @see calc()
* @see __sumdiff()
* @see count()
*/
function variance() {/*{{{*/
if (!array_key_exists('variance', $this->_calculatedValues)) {
$variance = $this->__calcVariance();
if (PEAR::isError($variance)) {
return $variance;
}
$this->_calculatedValues['variance'] = $variance;
}
return $this->_calculatedValues['variance'];
}/*}}}*/
/**
* Calculates the standard deviation (unbiased) of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the standard deviation on success, a PEAR_Error object otherwise
* @see calc()
* @see variance()
*/
function stDev() {/*{{{*/
if (!array_key_exists('stDev', $this->_calculatedValues)) {
$variance = $this->variance();
if (PEAR::isError($variance)) {
return $variance;
}
$this->_calculatedValues['stDev'] = sqrt($variance);
}
return $this->_calculatedValues['stDev'];
}/*}}}*/
/**
* Calculates the variance (unbiased) of the data points in the set
* given a fixed mean (average) value. Not used in calcBasic(), calcFull()
* or calc().
* Handles cummulative data sets correctly
*
* @access public
* @param numeric $mean the fixed mean value
* @return mixed the variance on success, a PEAR_Error object otherwise
* @see __sumdiff()
* @see count()
* @see variance()
*/
function varianceWithMean($mean) {/*{{{*/
return $this->__calcVariance($mean);
}/*}}}*/
/**
* Calculates the standard deviation (unbiased) of the data points in the set
* given a fixed mean (average) value. Not used in calcBasic(), calcFull()
* or calc().
* Handles cummulative data sets correctly
*
* @access public
* @param numeric $mean the fixed mean value
* @return mixed the standard deviation on success, a PEAR_Error object otherwise
* @see varianceWithMean()
* @see stDev()
*/
function stDevWithMean($mean) {/*{{{*/
$varianceWM = $this->varianceWithMean($mean);
if (PEAR::isError($varianceWM)) {
return $varianceWM;
}
return sqrt($varianceWM);
}/*}}}*/
/**
* Calculates the absolute deviation of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the absolute deviation on success, a PEAR_Error object otherwise
* @see calc()
* @see __sumabsdev()
* @see count()
* @see absDevWithMean()
*/
function absDev() {/*{{{*/
if (!array_key_exists('absDev', $this->_calculatedValues)) {
$absDev = $this->__calcAbsoluteDeviation();
if (PEAR::isError($absdev)) {
return $absdev;
}
$this->_calculatedValues['absDev'] = $absDev;
}
return $this->_calculatedValues['absDev'];
}/*}}}*/
/**
* Calculates the absolute deviation of the data points in the set
* given a fixed mean (average) value. Not used in calcBasic(), calcFull()
* or calc().
* Handles cummulative data sets correctly
*
* @access public
* @param numeric $mean the fixed mean value
* @return mixed the absolute deviation on success, a PEAR_Error object otherwise
* @see __sumabsdev()
* @see absDev()
*/
function absDevWithMean($mean) {/*{{{*/
return $this->__calcAbsoluteDeviation($mean);
}/*}}}*/
/**
* Calculates the skewness of the data distribution in the set
* The skewness measures the degree of asymmetry of a distribution,
* and is related to the third central moment of a distribution.
* A normal distribution has a skewness = 0
* A distribution with a tail off towards the high end of the scale
* (positive skew) has a skewness > 0
* A distribution with a tail off towards the low end of the scale
* (negative skew) has a skewness < 0
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the skewness value on success, a PEAR_Error object otherwise
* @see __sumdiff()
* @see count()
* @see stDev()
* @see calc()
*/
function skewness() {/*{{{*/
if (!array_key_exists('skewness', $this->_calculatedValues)) {
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$stDev = $this->stDev();
if (PEAR::isError($stDev)) {
return $stDev;
}
$sumdiff3 = $this->__sumdiff(3);
if (PEAR::isError($sumdiff3)) {
return $sumdiff3;
}
$this->_calculatedValues['skewness'] = ($sumdiff3 / ($count * pow($stDev, 3)));
}
return $this->_calculatedValues['skewness'];
}/*}}}*/
/**
* Calculates the kurtosis of the data distribution in the set
* The kurtosis measures the degrees of peakedness of a distribution.
* It is also called the "excess" or "excess coefficient", and is
* a normalized form of the fourth central moment of a distribution.
* A normal distributions has kurtosis = 0
* A narrow and peaked (leptokurtic) distribution has a
* kurtosis > 0
* A flat and wide (platykurtic) distribution has a kurtosis < 0
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the kurtosis value on success, a PEAR_Error object otherwise
* @see __sumdiff()
* @see count()
* @see stDev()
* @see calc()
*/
function kurtosis() {/*{{{*/
if (!array_key_exists('kurtosis', $this->_calculatedValues)) {
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$stDev = $this->stDev();
if (PEAR::isError($stDev)) {
return $stDev;
}
$sumdiff4 = $this->__sumdiff(4);
if (PEAR::isError($sumdiff4)) {
return $sumdiff4;
}
$this->_calculatedValues['kurtosis'] = ($sumdiff4 / ($count * pow($stDev, 4))) - 3;
}
return $this->_calculatedValues['kurtosis'];
}/*}}}*/
/**
* Calculates the median of a data set.
* The median is the value such that half of the points are below it
* in a sorted data set.
* If the number of values is odd, it is the middle item.
* If the number of values is even, is the average of the two middle items.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the median value on success, a PEAR_Error object otherwise
* @see count()
* @see calc()
*/
function median() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('median', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$arr =& $this->_dataExpanded;
} else {
$arr =& $this->_data;
}
$n = $this->count();
if (PEAR::isError($n)) {
return $n;
}
$h = intval($n / 2);
if ($n % 2 == 0) {
$median = ($arr[$h] + $arr[$h - 1]) / 2;
} else {
$median = $arr[$h + 1];
}
$this->_calculatedValues['median'] = $median;
}
return $this->_calculatedValues['median'];
}/*}}}*/
/**
* Calculates the mode of a data set.
* The mode is the value with the highest frequency in the data set.
* There can be more than one mode.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed an array of mode value on success, a PEAR_Error object otherwise
* @see frequency()
* @see calc()
*/
function mode() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('mode', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$arr = $this->_data;
} else {
$arr = $this->frequency();
}
arsort($arr);
$mcount = 1;
foreach ($arr as $val=>$freq) {
if ($mcount == 1) {
$mode = array($val);
$mfreq = $freq;
++$mcount;
continue;
}
if ($mfreq == $freq)
$mode[] = $val;
if ($mfreq > $freq)
break;
}
$this->_calculatedValues['mode'] = $mode;
}
return $this->_calculatedValues['mode'];
}/*}}}*/
/**
* Calculates the midrange of a data set.
* The midrange is the average of the minimum and maximum of the data set.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the midrange value on success, a PEAR_Error object otherwise
* @see min()
* @see max()
* @see calc()
*/
function midrange() {/*{{{*/
if (!array_key_exists('midrange', $this->_calculatedValues)) {
$min = $this->min();
if (PEAR::isError($min)) {
return $min;
}
$max = $this->max();
if (PEAR::isError($max)) {
return $max;
}
$this->_calculatedValues['midrange'] = (($max + $min) / 2);
}
return $this->_calculatedValues['midrange'];
}/*}}}*/
/**
* Calculates the geometrical mean of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the geometrical mean value on success, a PEAR_Error object otherwise
* @see calc()
* @see product()
* @see count()
*/
function geometricMean() {/*{{{*/
if (!array_key_exists('geometricMean', $this->_calculatedValues)) {
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$prod = $this->product();
if (PEAR::isError($prod)) {
return $prod;
}
if ($prod == 0.0) {
return 0.0;
}
if ($prod < 0) {
return PEAR::raiseError('The product of the data set is negative, geometric mean undefined.');
}
$this->_calculatedValues['geometricMean'] = pow($prod , 1 / $count);
}
return $this->_calculatedValues['geometricMean'];
}/*}}}*/
/**
* Calculates the harmonic mean of the data points in the set
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the harmonic mean value on success, a PEAR_Error object otherwise
* @see calc()
* @see count()
*/
function harmonicMean() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('harmonicMean', $this->_calculatedValues)) {
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$invsum = 0.0;
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach($this->_data as $val=>$freq) {
if ($val == 0) {
return PEAR::raiseError('cannot calculate a '.
'harmonic mean with data values of zero.');
}
$invsum += $freq / $val;
}
} else {
foreach($this->_data as $val) {
if ($val == 0) {
return PEAR::raiseError('cannot calculate a '.
'harmonic mean with data values of zero.');
}
$invsum += 1 / $val;
}
}
$this->_calculatedValues['harmonicMean'] = $count / $invsum;
}
return $this->_calculatedValues['harmonicMean'];
}/*}}}*/
/**
* Calculates the nth central moment (m{n}) of a data set.
*
* The definition of a sample central moment is:
*
* m{n} = 1/N * SUM { (xi - avg)^n }
*
* where: N = sample size, avg = sample mean.
*
* @access public
* @param integer $n moment to calculate
* @return mixed the numeric value of the moment on success, PEAR_Error otherwise
*/
function sampleCentralMoment($n) {/*{{{*/
if (!is_int($n) || $n < 1) {
return PEAR::isError('moment must be a positive integer >= 1.');
}
if ($n == 1) {
return 0;
}
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
if ($count == 0) {
return PEAR::raiseError("Cannot calculate {$n}th sample moment, ".
'there are zero data entries');
}
$sum = $this->__sumdiff($n);
if (PEAR::isError($sum)) {
return $sum;
}
return ($sum / $count);
}/*}}}*/
/**
* Calculates the nth raw moment (m{n}) of a data set.
*
* The definition of a sample central moment is:
*
* m{n} = 1/N * SUM { xi^n }
*
* where: N = sample size, avg = sample mean.
*
* @access public
* @param integer $n moment to calculate
* @return mixed the numeric value of the moment on success, PEAR_Error otherwise
*/
function sampleRawMoment($n) {/*{{{*/
if (!is_int($n) || $n < 1) {
return PEAR::isError('moment must be a positive integer >= 1.');
}
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
if ($count == 0) {
return PEAR::raiseError("Cannot calculate {$n}th raw moment, ".
'there are zero data entries.');
}
$sum = $this->sumN($n);
if (PEAR::isError($sum)) {
return $sum;
}
return ($sum / $count);
}/*}}}*/
/**
* Calculates the coefficient of variation of a data set.
* The coefficient of variation measures the spread of a set of data
* as a proportion of its mean. It is often expressed as a percentage.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed the coefficient of variation on success, a PEAR_Error object otherwise
* @see stDev()
* @see mean()
* @see calc()
*/
function coeffOfVariation() {/*{{{*/
if (!array_key_exists('coeffOfVariation', $this->_calculatedValues)) {
$mean = $this->mean();
if (PEAR::isError($mean)) {
return $mean;
}
if ($mean == 0.0) {
return PEAR::raiseError('cannot calculate the coefficient '.
'of variation, mean of sample is zero');
}
$stDev = $this->stDev();
if (PEAR::isError($stDev)) {
return $stDev;
}
$this->_calculatedValues['coeffOfVariation'] = $stDev / $mean;
}
return $this->_calculatedValues['coeffOfVariation'];
}/*}}}*/
/**
* Calculates the standard error of the mean.
* It is the standard deviation of the sampling distribution of
* the mean. The formula is:
*
* S.E. Mean = SD / (N)^(1/2)
*
* This formula does not assume a normal distribution, and shows
* that the size of the standard error of the mean is inversely
* proportional to the square root of the sample size.
*
* @access public
* @return mixed the standard error of the mean on success, a PEAR_Error object otherwise
* @see stDev()
* @see count()
* @see calc()
*/
function stdErrorOfMean() {/*{{{*/
if (!array_key_exists('stdErrorOfMean', $this->_calculatedValues)) {
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$stDev = $this->stDev();
if (PEAR::isError($stDev)) {
return $stDev;
}
$this->_calculatedValues['stdErrorOfMean'] = $stDev / sqrt($count);
}
return $this->_calculatedValues['stdErrorOfMean'];
}/*}}}*/
/**
* Calculates the value frequency table of a data set.
* Handles cummulative data sets correctly
*
* @access public
* @return mixed an associative array of value=>frequency items on success, a PEAR_Error object otherwise
* @see min()
* @see max()
* @see calc()
*/
function frequency() {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (!array_key_exists('frequency', $this->_calculatedValues)) {
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$freq = $this->_data;
} else {
$freq = array();
foreach ($this->_data as $val) {
$freq["$val"]++;
}
ksort($freq);
}
$this->_calculatedValues['frequency'] = $freq;
}
return $this->_calculatedValues['frequency'];
}/*}}}*/
/**
* The quartiles are defined as the values that divide a sorted
* data set into four equal-sized subsets, and correspond to the
* 25th, 50th, and 75th percentiles.
*
* @access public
* @return mixed an associative array of quartiles on success, a PEAR_Error otherwise
* @see percentile()
*/
function quartiles() {/*{{{*/
if (!array_key_exists('quartiles', $this->_calculatedValues)) {
$q1 = $this->percentile(25);
if (PEAR::isError($q1)) {
return $q1;
}
$q2 = $this->percentile(50);
if (PEAR::isError($q2)) {
return $q2;
}
$q3 = $this->percentile(75);
if (PEAR::isError($q3)) {
return $q3;
}
$this->_calculatedValues['quartiles'] = array (
'25' => $q1,
'50' => $q2,
'75' => $q3
);
}
return $this->_calculatedValues['quartiles'];
}/*}}}*/
/**
* The interquartile mean is defined as the mean of the values left
* after discarding the lower 25% and top 25% ranked values, i.e.:
*
* interquart mean = mean()
*
* where: P = percentile
*
* @todo need to double check the equation
* @access public
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
*/
function interquartileMean() {/*{{{*/
if (!array_key_exists('interquartileMean', $this->_calculatedValues)) {
$quart = $this->quartiles();
if (PEAR::isError($quart)) {
return $quart;
}
$q3 = $quart['75'];
$q1 = $quart['25'];
$sum = 0;
$n = 0;
foreach ($this->getData(true) as $val) {
if ($val >= $q1 && $val <= $q3) {
$sum += $val;
++$n;
}
}
if ($n == 0) {
return PEAR::raiseError('error calculating interquartile mean, '.
'empty interquartile range of values.');
}
$this->_calculatedValues['interquartileMean'] = $sum / $n;
}
return $this->_calculatedValues['interquartileMean'];
}/*}}}*/
/**
* The interquartile range is the distance between the 75th and 25th
* percentiles. Basically the range of the middle 50% of the data set,
* and thus is not affected by outliers or extreme values.
*
* interquart range = P(75) - P(25)
*
* where: P = percentile
*
* @access public
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
*/
function interquartileRange() {/*{{{*/
if (!array_key_exists('interquartileRange', $this->_calculatedValues)) {
$quart = $this->quartiles();
if (PEAR::isError($quart)) {
return $quart;
}
$q3 = $quart['75'];
$q1 = $quart['25'];
$this->_calculatedValues['interquartileRange'] = $q3 - $q1;
}
return $this->_calculatedValues['interquartileRange'];
}/*}}}*/
/**
* The quartile deviation is half of the interquartile range value
*
* quart dev = (P(75) - P(25)) / 2
*
* where: P = percentile
*
* @access public
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
* @see interquartileRange()
*/
function quartileDeviation() {/*{{{*/
if (!array_key_exists('quartileDeviation', $this->_calculatedValues)) {
$iqr = $this->interquartileRange();
if (PEAR::isError($iqr)) {
return $iqr;
}
$this->_calculatedValues['quartileDeviation'] = $iqr / 2;
}
return $this->_calculatedValues['quartileDeviation'];
}/*}}}*/
/**
* The quartile variation coefficient is defines as follows:
*
* quart var coeff = 100 * (P(75) - P(25)) / (P(75) + P(25))
*
* where: P = percentile
*
* @todo need to double check the equation
* @access public
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
*/
function quartileVariationCoefficient() {/*{{{*/
if (!array_key_exists('quartileVariationCoefficient', $this->_calculatedValues)) {
$quart = $this->quartiles();
if (PEAR::isError($quart)) {
return $quart;
}
$q3 = $quart['75'];
$q1 = $quart['25'];
$d = $q3 - $q1;
$s = $q3 + $q1;
$this->_calculatedValues['quartileVariationCoefficient'] = 100 * $d / $s;
}
return $this->_calculatedValues['quartileVariationCoefficient'];
}/*}}}*/
/**
* The quartile skewness coefficient (also known as Bowley Skewness),
* is defined as follows:
*
* quart skewness coeff = (P(25) - 2*P(50) + P(75)) / (P(75) - P(25))
*
* where: P = percentile
*
* @todo need to double check the equation
* @access public
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
*/
function quartileSkewnessCoefficient() {/*{{{*/
if (!array_key_exists('quartileSkewnessCoefficient', $this->_calculatedValues)) {
$quart = $this->quartiles();
if (PEAR::isError($quart)) {
return $quart;
}
$q3 = $quart['75'];
$q2 = $quart['50'];
$q1 = $quart['25'];
$d = $q3 - 2*$q2 + $q1;
$s = $q3 - $q1;
$this->_calculatedValues['quartileSkewnessCoefficient'] = $d / $s;
}
return $this->_calculatedValues['quartileSkewnessCoefficient'];
}/*}}}*/
/**
* The pth percentile is the value such that p% of the a sorted data set
* is smaller than it, and (100 - p)% of the data is larger.
*
* A quick algorithm to pick the appropriate value from a sorted data
* set is as follows:
*
* - Count the number of values: n
* - Calculate the position of the value in the data list: i = p * (n + 1)
* - if i is an integer, return the data at that position
* - if i < 1, return the minimum of the data set
* - if i > n, return the maximum of the data set
* - otherwise, average the entries at adjacent positions to i
*
* The median is the 50th percentile value.
*
* @todo need to double check generality of the algorithm
*
* @access public
* @param numeric $p the percentile to estimate, e.g. 25 for 25th percentile
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see quartiles()
* @see median()
*/
function percentile($p) {/*{{{*/
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
$data =& $this->_dataExpanded;
} else {
$data =& $this->_data;
}
$obsidx = $p * ($count + 1) / 100;
if (intval($obsidx) == $obsidx) {
return $data[($obsidx - 1)];
} elseif ($obsidx < 1) {
return $data[0];
} elseif ($obsidx > $count) {
return $data[($count - 1)];
} else {
$left = floor($obsidx - 1);
$right = ceil($obsidx - 1);
return ($data[$left] + $data[$right]) / 2;
}
}/*}}}*/
// private methods
/**
* Utility function to calculate: SUM { (xi - mean)^n }
*
* @access private
* @param numeric $power the exponent
* @param optional double $mean the data set mean value
* @return mixed the sum on success, a PEAR_Error object otherwise
*
* @see stDev()
* @see variaceWithMean();
* @see skewness();
* @see kurtosis();
*/
function __sumdiff($power, $mean=null) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (is_null($mean)) {
$mean = $this->mean();
if (PEAR::isError($mean)) {
return $mean;
}
}
$sdiff = 0;
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach ($this->_data as $val=>$freq) {
$sdiff += $freq * pow((double)($val - $mean), (double)$power);
}
} else {
foreach ($this->_data as $val)
$sdiff += pow((double)($val - $mean), (double)$power);
}
return $sdiff;
}/*}}}*/
/**
* Utility function to calculate the variance with or without
* a fixed mean
*
* @access private
* @param $mean the fixed mean to use, null as default
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see variance()
* @see varianceWithMean()
*/
function __calcVariance($mean = null) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
$sumdiff2 = $this->__sumdiff(2, $mean);
if (PEAR::isError($sumdiff2)) {
return $sumdiff2;
}
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
if ($count == 1) {
return PEAR::raiseError('cannot calculate variance of a singe data point');
}
return ($sumdiff2 / ($count - 1));
}/*}}}*/
/**
* Utility function to calculate the absolute deviation with or without
* a fixed mean
*
* @access private
* @param $mean the fixed mean to use, null as default
* @return mixed a numeric value on success, a PEAR_Error otherwise
* @see absDev()
* @see absDevWithMean()
*/
function __calcAbsoluteDeviation($mean = null) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
$count = $this->count();
if (PEAR::isError($count)) {
return $count;
}
$sumabsdev = $this->__sumabsdev($mean);
if (PEAR::isError($sumabsdev)) {
return $sumabsdev;
}
return $sumabsdev / $count;
}/*}}}*/
/**
* Utility function to calculate: SUM { | xi - mean | }
*
* @access private
* @param optional double $mean the mean value for the set or population
* @return mixed the sum on success, a PEAR_Error object otherwise
*
* @see absDev()
* @see absDevWithMean()
*/
function __sumabsdev($mean=null) {/*{{{*/
if ($this->_data == null) {
return PEAR::raiseError('data has not been set');
}
if (is_null($mean)) {
$mean = $this->mean();
}
$sdev = 0;
if ($this->_dataOption == STATS_DATA_CUMMULATIVE) {
foreach ($this->_data as $val=>$freq) {
$sdev += $freq * abs($val - $mean);
}
} else {
foreach ($this->_data as $val) {
$sdev += abs($val - $mean);
}
}
return $sdev;
}/*}}}*/
/**
* Utility function to format a PEAR_Error to be used by calc(),
* calcBasic() and calcFull()
*
* @access private
* @param mixed $v value to be formatted
* @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default),
* or only the error message will be returned (when false)
* @return mixed if the value is a PEAR_Error object, and $useErrorObject
* is false, then a string with the error message will be returned,
* otherwise the value will not be modified and returned as passed.
*/
function __format($v, $useErrorObject=true) {/*{{{*/
if (PEAR::isError($v) && $useErrorObject == false) {
return $v->getMessage();
} else {
return $v;
}
}/*}}}*/
/**
* Utility function to validate the data and modify it
* according to the current null handling option
*
* @access private
* @return mixed true on success, a PEAR_Error object otherwise
*
* @see setData()
*/
function _validate() {/*{{{*/
$flag = ($this->_dataOption == STATS_DATA_CUMMULATIVE);
foreach ($this->_data as $key=>$value) {
$d = ($flag) ? $key : $value;
$v = ($flag) ? $value : $key;
if (!is_numeric($d)) {
switch ($this->_nullOption) {
case STATS_IGNORE_NULL :
unset($this->_data["$key"]);
break;
case STATS_USE_NULL_AS_ZERO:
if ($flag) {
unset($this->_data["$key"]);
$this->_data[0] += $v;
} else {
$this->_data[$key] = 0;
}
break;
case STATS_REJECT_NULL :
default:
return PEAR::raiseError('data rejected, contains NULL values');
break;
}
}
}
if ($flag) {
ksort($this->_data);
$this->_dataExpanded = array();
foreach ($this->_data as $val=>$freq) {
$this->_dataExpanded = array_pad($this->_dataExpanded, count($this->_dataExpanded) + $freq, $val);
}
sort($this->_dataExpanded);
} else {
sort($this->_data);
}
return true;
}/*}}}*/
}/*}}}*/
// vim: ts=4:sw=4:et:
// vim6: fdl=1: fdm=marker:
?>
PHPExcel/Shared/JAMA/examples/LMQuadTest.php 0000666 00000003756 15016734321 0014425 0 ustar 00 val($x[$i], $a);
print("Quad ".$c.",".$r." -> ".$y[$i]."
");
$s[$i] = 1.;
++$i;
}
}
print("quad x= ");
$qx = new Matrix($x);
$qx->print(10, 2);
print("quad y= ");
$qy = new Matrix($y, $npts);
$qy->print(10, 2);
$o[0] = $x;
$o[1] = $a;
$o[2] = $y;
$o[3] = $s;
return $o;
} // function testdata()
} // class LMQuadTest
PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php 0000666 00000002614 15016734321 0017004 0 ustar 00 solve($b);
return $s->getRowPackedCopy();
} // function findPolynomialFactors()
} // class LagrangeInterpolation
$x = array(2.0, 1.0, 3.0);
$y = array(3.0, 4.0, 7.0);
$li = new LagrangeInterpolation;
$f = $li->findPolynomialFactors($x, $y);
for ($i = 0; $i < 3; ++$i) {
echo $f[$i]."
";
}
PHPExcel/Shared/JAMA/examples/benchmark.php 0000666 00000015172 15016734321 0014367 0 ustar 00 stat->setData($times);
$stats = $this->stat->calcFull();
echo '
';
echo 'n: | ' . $stats['count'] . ' |
';
echo 'Mean: | ' . $stats['mean'] . ' |
';
echo 'Min.: | ' . $stats['min'] . ' |
';
echo 'Max.: | ' . $stats['max'] . ' |
';
echo 'σ: | ' . $stats['stdev'] . ' |
';
echo 'Variance: | ' . $stats['variance'] . ' |
';
echo 'Range: | ' . $stats['range'] . ' |
';
echo '
';
return $stats;
} // function displayStats()
function runEig($n = 4, $t = 100) {
$times = array();
for ($i = 0; $i < $t; ++$i) {
$M = Matrix::random($n, $n);
$start_time = $this->microtime_float();
$E = new EigenvalueDecomposition($M);
$stop_time = $this->microtime_float();
$times[] = $stop_time - $start_time;
}
return $times;
} // function runEig()
function runLU($n = 4, $t = 100) {
$times = array();
for ($i = 0; $i < $t; ++$i) {
$M = Matrix::random($n, $n);
$start_time = $this->microtime_float();
$E = new LUDecomposition($M);
$stop_time = $this->microtime_float();
$times[] = $stop_time - $start_time;
}
return $times;
} // function runLU()
function runQR($n = 4, $t = 100) {
$times = array();
for ($i = 0; $i < $t; ++$i) {
$M = Matrix::random($n, $n);
$start_time = $this->microtime_float();
$E = new QRDecomposition($M);
$stop_time = $this->microtime_float();
$times[] = $stop_time - $start_time;
}
return $times;
} // function runQR()
function runCholesky($n = 4, $t = 100) {
$times = array();
for ($i = 0; $i < $t; ++$i) {
$M = Matrix::random($n, $n);
$start_time = $this->microtime_float();
$E = new CholeskyDecomposition($M);
$stop_time = $this->microtime_float();
$times[] = $stop_time - $start_time;
}
return $times;
} // function runCholesky()
function runSVD($n = 4, $t = 100) {
$times = array();
for ($i = 0; $i < $t; ++$i) {
$M = Matrix::random($n, $n);
$start_time = $this->microtime_float();
$E = new SingularValueDecomposition($M);
$stop_time = $this->microtime_float();
$times[] = $stop_time - $start_time;
}
return $times;
} // function runSVD()
function run() {
$n = 8;
$t = 16;
$sum = 0;
echo "Cholesky decomposition: $t random {$n}x{$n} matrices
";
$r = $this->displayStats($this->runCholesky($n, $t));
$sum += $r['mean'] * $n;
echo '
';
echo "Eigenvalue decomposition: $t random {$n}x{$n} matrices
";
$r = $this->displayStats($this->runEig($n, $t));
$sum += $r['mean'] * $n;
echo '
';
echo "LU decomposition: $t random {$n}x{$n} matrices
";
$r = $this->displayStats($this->runLU($n, $t));
$sum += $r['mean'] * $n;
echo '
';
echo "QR decomposition: $t random {$n}x{$n} matrices
";
$r = $this->displayStats($this->runQR($n, $t));
$sum += $r['mean'] * $n;
echo '
';
echo "Singular Value decomposition: $t random {$n}x{$n} matrices
";
$r = $this->displayStats($this->runSVD($n, $t));
$sum += $r['mean'] * $n;
return $sum;
} // function run()
public function __construct() {
$this->stat = new Base();
} // function Benchmark()
} // class Benchmark (end MagicSquareExample)
$benchmark = new Benchmark();
switch($_REQUEST['decomposition']) {
case 'cholesky':
$m = array();
for ($i = 2; $i <= 8; $i *= 2) {
$t = 32 / $i;
echo "Cholesky decomposition: $t random {$i}x{$i} matrices
";
$s = $benchmark->displayStats($benchmark->runCholesky($i, $t));
$m[$i] = $s['mean'];
echo "
";
}
echo '';
foreach($m as $x => $y) {
echo "$x\t" . 1000*$y . "\n";
}
echo '
';
break;
case 'eigenvalue':
$m = array();
for ($i = 2; $i <= 8; $i *= 2) {
$t = 32 / $i;
echo "Eigenvalue decomposition: $t random {$i}x{$i} matrices
";
$s = $benchmark->displayStats($benchmark->runEig($i, $t));
$m[$i] = $s['mean'];
echo "
";
}
echo '';
foreach($m as $x => $y) {
echo "$x\t" . 1000*$y . "\n";
}
echo '
';
break;
case 'lu':
$m = array();
for ($i = 2; $i <= 8; $i *= 2) {
$t = 32 / $i;
echo "LU decomposition: $t random {$i}x{$i} matrices
";
$s = $benchmark->displayStats($benchmark->runLU($i, $t));
$m[$i] = $s['mean'];
echo "
";
}
echo '';
foreach($m as $x => $y) {
echo "$x\t" . 1000*$y . "\n";
}
echo '
';
break;
case 'qr':
$m = array();
for ($i = 2; $i <= 8; $i *= 2) {
$t = 32 / $i;
echo "QR decomposition: $t random {$i}x{$i} matrices
";
$s = $benchmark->displayStats($benchmark->runQR($i, $t));
$m[$i] = $s['mean'];
echo "
";
}
echo '';
foreach($m as $x => $y) {
echo "$x\t" . 1000*$y . "\n";
}
echo '
';
break;
case 'svd':
$m = array();
for($i = 2; $i <= 8; $i *= 2) {
$t = 32 / $i;
echo "Singular value decomposition: $t random {$i}x{$i} matrices
";
$s = $benchmark->displayStats($benchmark->runSVD($i, $t));
$m[$i] = $s['mean'];
echo "
";
}
echo '';
foreach($m as $x => $y) {
echo "$x\t" . 1000*$y . "\n";
}
echo '
';
break;
case 'all':
$s = $benchmark->run();
print("
Total: {$s}s
");
break;
default:
?>
$n+1
*/
function polyfit($X, $Y, $n) {
for ($i = 0; $i < sizeof($X); ++$i)
for ($j = 0; $j <= $n; ++$j)
$A[$i][$j] = pow($X[$i], $j);
for ($i=0; $i < sizeof($Y); ++$i)
$B[$i] = array($Y[$i]);
$matrixA = new Matrix($A);
$matrixB = new Matrix($B);
$C = $matrixA->solve($matrixB);
return $C->getMatrix(0, $n, 0, 1);
}
function printpoly( $C = null ) {
for($i = $C->m - 1; $i >= 0; --$i) {
$r = $C->get($i, 0);
if ( abs($r) <= pow(10, -9) )
$r = 0;
if ($i == $C->m - 1)
echo $r . "x$i";
else if ($i < $C->m - 1)
echo " + " . $r . "x$i";
else if ($i == 0)
echo " + " . $r;
}
}
$X = array(0,1,2,3,4,5);
$Y = array(4,3,12,67,228, 579);
$points = new Matrix(array($X, $Y));
$points->toHTML();
printpoly(polyfit($X, $Y, 4));
echo '
';
$X = array(0,1,2,3,4,5);
$Y = array(1,2,5,10,17, 26);
$points = new Matrix(array($X, $Y));
$points->toHTML();
printpoly(polyfit($X, $Y, 2));
echo '
';
$X = array(0,1,2,3,4,5,6);
$Y = array(-90,-104,-178,-252,-26, 1160, 4446);
$points = new Matrix(array($X, $Y));
$points->toHTML();
printpoly(polyfit($X, $Y, 5));
echo '
';
$X = array(0,1,2,3,4);
$Y = array(mt_rand(0, 10), mt_rand(40, 80), mt_rand(240, 400), mt_rand(1800, 2215), mt_rand(8000, 9000));
$points = new Matrix(array($X, $Y));
$points->toHTML();
printpoly(polyfit($X, $Y, 3));
?>
PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php 0000666 00000002431 15016734321 0016717 0 ustar 00 solve($b);
return $s->getRowPackedCopy();
} // function findPolynomialFactors()
} // class LagrangeInterpolation
$x = array(2.0, 1.0, 3.0);
$y = array(3.0, 4.0, 7.0);
$li = new LagrangeInterpolation;
$f = $li->findPolynomialFactors($x, $y);
for ($i = 0; $i < 3; ++$i) {
echo $f[$i]."
";
}
PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php 0000666 00000012140 15016734321 0016217 0 ustar 00 val($x[$i], $a);
$d = $d / $s[$i];
$sum = $sum + ($d*$d);
}
return $sum;
} // function chiSquared()
/**
* Minimize E = sum {(y[k] - f(x[k],a)) / s[k]}^2
* The individual errors are optionally scaled by s[k].
* Note that LMfunc implements the value and gradient of f(x,a),
* NOT the value and gradient of E with respect to a!
*
* @param x array of domain points, each may be multidimensional
* @param y corresponding array of values
* @param a the parameters/state of the model
* @param vary false to indicate the corresponding a[k] is to be held fixed
* @param s2 sigma^2 for point i
* @param lambda blend between steepest descent (lambda high) and
* jump to bottom of quadratic (lambda zero).
* Start with 0.001.
* @param termepsilon termination accuracy (0.01)
* @param maxiter stop and return after this many iterations if not done
* @param verbose set to zero (no prints), 1, 2
*
* @return the new lambda for future iterations.
* Can use this and maxiter to interleave the LM descent with some other
* task, setting maxiter to something small.
*/
function solve($x, $a, $y, $s, $vary, $f, $lambda, $termepsilon, $maxiter, $verbose) {
$npts = count($y);
$nparm = count($a);
if ($verbose > 0) {
print("solve x[".count($x)."][".count($x[0])."]");
print(" a[".count($a)."]");
println(" y[".count(length)."]");
}
$e0 = $this->chiSquared($x, $a, $y, $s, $f);
//double lambda = 0.001;
$done = false;
// g = gradient, H = hessian, d = step to minimum
// H d = -g, solve for d
$H = array();
$g = array();
//double[] d = new double[nparm];
$oos2 = array();
for($i = 0; $i < $npts; ++$i) {
$oos2[$i] = 1./($s[$i]*$s[$i]);
}
$iter = 0;
$term = 0; // termination count test
do {
++$iter;
// hessian approximation
for( $r = 0; $r < $nparm; ++$r) {
for( $c = 0; $c < $nparm; ++$c) {
for( $i = 0; $i < $npts; ++$i) {
if ($i == 0) $H[$r][$c] = 0.;
$xi = $x[$i];
$H[$r][$c] += ($oos2[$i] * $f->grad($xi, $a, $r) * $f->grad($xi, $a, $c));
} //npts
} //c
} //r
// boost diagonal towards gradient descent
for( $r = 0; $r < $nparm; ++$r)
$H[$r][$r] *= (1. + $lambda);
// gradient
for( $r = 0; $r < $nparm; ++$r) {
for( $i = 0; $i < $npts; ++$i) {
if ($i == 0) $g[$r] = 0.;
$xi = $x[$i];
$g[$r] += ($oos2[$i] * ($y[$i]-$f->val($xi,$a)) * $f->grad($xi, $a, $r));
}
} //npts
// scale (for consistency with NR, not necessary)
if ($false) {
for( $r = 0; $r < $nparm; ++$r) {
$g[$r] = -0.5 * $g[$r];
for( $c = 0; $c < $nparm; ++$c) {
$H[$r][$c] *= 0.5;
}
}
}
// solve H d = -g, evaluate error at new location
//double[] d = DoubleMatrix.solve(H, g);
// double[] d = (new Matrix(H)).lu().solve(new Matrix(g, nparm)).getRowPackedCopy();
//double[] na = DoubleVector.add(a, d);
// double[] na = (new Matrix(a, nparm)).plus(new Matrix(d, nparm)).getRowPackedCopy();
// double e1 = chiSquared(x, na, y, s, f);
// if (verbose > 0) {
// System.out.println("\n\niteration "+iter+" lambda = "+lambda);
// System.out.print("a = ");
// (new Matrix(a, nparm)).print(10, 2);
// if (verbose > 1) {
// System.out.print("H = ");
// (new Matrix(H)).print(10, 2);
// System.out.print("g = ");
// (new Matrix(g, nparm)).print(10, 2);
// System.out.print("d = ");
// (new Matrix(d, nparm)).print(10, 2);
// }
// System.out.print("e0 = " + e0 + ": ");
// System.out.print("moved from ");
// (new Matrix(a, nparm)).print(10, 2);
// System.out.print("e1 = " + e1 + ": ");
// if (e1 < e0) {
// System.out.print("to ");
// (new Matrix(na, nparm)).print(10, 2);
// } else {
// System.out.println("move rejected");
// }
// }
// termination test (slightly different than NR)
// if (Math.abs(e1-e0) > termepsilon) {
// term = 0;
// } else {
// term++;
// if (term == 4) {
// System.out.println("terminating after " + iter + " iterations");
// done = true;
// }
// }
// if (iter >= maxiter) done = true;
// in the C++ version, found that changing this to e1 >= e0
// was not a good idea. See comment there.
//
// if (e1 > e0 || Double.isNaN(e1)) { // new location worse than before
// lambda *= 10.;
// } else { // new location better, accept new parameters
// lambda *= 0.1;
// e0 = e1;
// // simply assigning a = na will not get results copied back to caller
// for( int i = 0; i < nparm; i++ ) {
// if (vary[i]) a[i] = na[i];
// }
// }
} while(!$done);
return $lambda;
} // function solve()
} // class LevenbergMarquardt
PHPExcel/Shared/JAMA/LUDecomposition.php 0000666 00000013312 15016734321 0013666 0 ustar 00 = n, the LU decomposition is an m-by-n
* unit lower triangular matrix L, an n-by-n upper triangular matrix U,
* and a permutation vector piv of length m so that A(piv,:) = L*U.
* If m < n, then L is m-by-m and U is m-by-n.
*
* The LU decompostion with pivoting always exists, even if the matrix is
* singular, so the constructor will never fail. The primary use of the
* LU decomposition is in the solution of square systems of simultaneous
* linear equations. This will fail if isNonsingular() returns false.
*
* @author Paul Meagher
* @author Bartosz Matosiuk
* @author Michael Bommarito
* @version 1.1
* @license PHP v3.0
*/
class LUDecomposition {
/**
* Decomposition storage
* @var array
*/
private $LU = array();
/**
* Row dimension.
* @var int
*/
private $m;
/**
* Column dimension.
* @var int
*/
private $n;
/**
* Pivot sign.
* @var int
*/
private $pivsign;
/**
* Internal storage of pivot vector.
* @var array
*/
private $piv = array();
/**
* LU Decomposition constructor.
*
* @param $A Rectangular matrix
* @return Structure to access L, U and piv.
*/
public function __construct($A) {
if ($A instanceof Matrix) {
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
$this->LU = $A->getArrayCopy();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
for ($i = 0; $i < $this->m; ++$i) {
$this->piv[$i] = $i;
}
$this->pivsign = 1;
$LUrowi = $LUcolj = array();
// Outer loop.
for ($j = 0; $j < $this->n; ++$j) {
// Make a copy of the j-th column to localize references.
for ($i = 0; $i < $this->m; ++$i) {
$LUcolj[$i] = &$this->LU[$i][$j];
}
// Apply previous transformations.
for ($i = 0; $i < $this->m; ++$i) {
$LUrowi = $this->LU[$i];
// Most of the time is spent in the following dot product.
$kmax = min($i,$j);
$s = 0.0;
for ($k = 0; $k < $kmax; ++$k) {
$s += $LUrowi[$k] * $LUcolj[$k];
}
$LUrowi[$j] = $LUcolj[$i] -= $s;
}
// Find pivot and exchange if necessary.
$p = $j;
for ($i = $j+1; $i < $this->m; ++$i) {
if (abs($LUcolj[$i]) > abs($LUcolj[$p])) {
$p = $i;
}
}
if ($p != $j) {
for ($k = 0; $k < $this->n; ++$k) {
$t = $this->LU[$p][$k];
$this->LU[$p][$k] = $this->LU[$j][$k];
$this->LU[$j][$k] = $t;
}
$k = $this->piv[$p];
$this->piv[$p] = $this->piv[$j];
$this->piv[$j] = $k;
$this->pivsign = $this->pivsign * -1;
}
// Compute multipliers.
if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) {
for ($i = $j+1; $i < $this->m; ++$i) {
$this->LU[$i][$j] /= $this->LU[$j][$j];
}
}
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function __construct()
/**
* Get lower triangular factor.
*
* @return array Lower triangular factor
*/
public function getL() {
for ($i = 0; $i < $this->m; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i > $j) {
$L[$i][$j] = $this->LU[$i][$j];
} elseif ($i == $j) {
$L[$i][$j] = 1.0;
} else {
$L[$i][$j] = 0.0;
}
}
}
return new Matrix($L);
} // function getL()
/**
* Get upper triangular factor.
*
* @return array Upper triangular factor
*/
public function getU() {
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i <= $j) {
$U[$i][$j] = $this->LU[$i][$j];
} else {
$U[$i][$j] = 0.0;
}
}
}
return new Matrix($U);
} // function getU()
/**
* Return pivot permutation vector.
*
* @return array Pivot vector
*/
public function getPivot() {
return $this->piv;
} // function getPivot()
/**
* Alias for getPivot
*
* @see getPivot
*/
public function getDoublePivot() {
return $this->getPivot();
} // function getDoublePivot()
/**
* Is the matrix nonsingular?
*
* @return true if U, and hence A, is nonsingular.
*/
public function isNonsingular() {
for ($j = 0; $j < $this->n; ++$j) {
if ($this->LU[$j][$j] == 0) {
return false;
}
}
return true;
} // function isNonsingular()
/**
* Count determinants
*
* @return array d matrix deterninat
*/
public function det() {
if ($this->m == $this->n) {
$d = $this->pivsign;
for ($j = 0; $j < $this->n; ++$j) {
$d *= $this->LU[$j][$j];
}
return $d;
} else {
throw new Exception(JAMAError(MatrixDimensionException));
}
} // function det()
/**
* Solve A*X = B
*
* @param $B A Matrix with as many rows as A and any number of columns.
* @return X so that L*U*X = B(piv,:)
* @exception IllegalArgumentException Matrix row dimensions must agree.
* @exception RuntimeException Matrix is singular.
*/
public function solve($B) {
if ($B->getRowDimension() == $this->m) {
if ($this->isNonsingular()) {
// Copy right hand side with pivoting
$nx = $B->getColumnDimension();
$X = $B->getMatrix($this->piv, 0, $nx-1);
// Solve L*Y = B(piv,:)
for ($k = 0; $k < $this->n; ++$k) {
for ($i = $k+1; $i < $this->n; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
}
}
}
// Solve U*X = Y;
for ($k = $this->n-1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$k][$j] /= $this->LU[$k][$k];
}
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k];
}
}
}
return $X;
} else {
throw new Exception(JAMAError(MatrixSingularException));
}
} else {
throw new Exception(JAMAError(MatrixSquareException));
}
} // function solve()
} // class LUDecomposition
PHPExcel/Shared/JAMA/QRDecomposition.php 0000666 00000012541 15016734321 0013673 0 ustar 00 = n, the QR decomposition is an m-by-n
* orthogonal matrix Q and an n-by-n upper triangular matrix R so that
* A = Q*R.
*
* The QR decompostion always exists, even if the matrix does not have
* full rank, so the constructor will never fail. The primary use of the
* QR decomposition is in the least squares solution of nonsquare systems
* of simultaneous linear equations. This will fail if isFullRank()
* returns false.
*
* @author Paul Meagher
* @license PHP v3.0
* @version 1.1
*/
class QRDecomposition {
/**
* Array for internal storage of decomposition.
* @var array
*/
private $QR = array();
/**
* Row dimension.
* @var integer
*/
private $m;
/**
* Column dimension.
* @var integer
*/
private $n;
/**
* Array for internal storage of diagonal of R.
* @var array
*/
private $Rdiag = array();
/**
* QR Decomposition computed by Householder reflections.
*
* @param matrix $A Rectangular matrix
* @return Structure to access R and the Householder vectors and compute Q.
*/
public function __construct($A) {
if($A instanceof Matrix) {
// Initialize.
$this->QR = $A->getArrayCopy();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
// Main loop.
for ($k = 0; $k < $this->n; ++$k) {
// Compute 2-norm of k-th column without under/overflow.
$nrm = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$nrm = hypo($nrm, $this->QR[$i][$k]);
}
if ($nrm != 0.0) {
// Form k-th Householder vector.
if ($this->QR[$k][$k] < 0) {
$nrm = -$nrm;
}
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$k] /= $nrm;
}
$this->QR[$k][$k] += 1.0;
// Apply transformation to remaining columns.
for ($j = $k+1; $j < $this->n; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $this->QR[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
$this->Rdiag[$k] = -$nrm;
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function __construct()
/**
* Is the matrix full rank?
*
* @return boolean true if R, and hence A, has full rank, else false.
*/
public function isFullRank() {
for ($j = 0; $j < $this->n; ++$j) {
if ($this->Rdiag[$j] == 0) {
return false;
}
}
return true;
} // function isFullRank()
/**
* Return the Householder vectors
*
* @return Matrix Lower trapezoidal matrix whose columns define the reflections
*/
public function getH() {
for ($i = 0; $i < $this->m; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i >= $j) {
$H[$i][$j] = $this->QR[$i][$j];
} else {
$H[$i][$j] = 0.0;
}
}
}
return new Matrix($H);
} // function getH()
/**
* Return the upper triangular factor
*
* @return Matrix upper triangular factor
*/
public function getR() {
for ($i = 0; $i < $this->n; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
if ($i < $j) {
$R[$i][$j] = $this->QR[$i][$j];
} elseif ($i == $j) {
$R[$i][$j] = $this->Rdiag[$i];
} else {
$R[$i][$j] = 0.0;
}
}
}
return new Matrix($R);
} // function getR()
/**
* Generate and return the (economy-sized) orthogonal factor
*
* @return Matrix orthogonal factor
*/
public function getQ() {
for ($k = $this->n-1; $k >= 0; --$k) {
for ($i = 0; $i < $this->m; ++$i) {
$Q[$i][$k] = 0.0;
}
$Q[$k][$k] = 1.0;
for ($j = $k; $j < $this->n; ++$j) {
if ($this->QR[$k][$k] != 0) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $Q[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$Q[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
}
/*
for($i = 0; $i < count($Q); ++$i) {
for($j = 0; $j < count($Q); ++$j) {
if(! isset($Q[$i][$j]) ) {
$Q[$i][$j] = 0;
}
}
}
*/
return new Matrix($Q);
} // function getQ()
/**
* Least squares solution of A*X = B
*
* @param Matrix $B A Matrix with as many rows as A and any number of columns.
* @return Matrix Matrix that minimizes the two norm of Q*R*X-B.
*/
public function solve($B) {
if ($B->getRowDimension() == $this->m) {
if ($this->isFullRank()) {
// Copy right hand side
$nx = $B->getColumnDimension();
$X = $B->getArrayCopy();
// Compute Y = transpose(Q)*B
for ($k = 0; $k < $this->n; ++$k) {
for ($j = 0; $j < $nx; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $X[$i][$j];
}
$s = -$s/$this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$X[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
// Solve R*X = Y;
for ($k = $this->n-1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X[$k][$j] /= $this->Rdiag[$k];
}
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k];
}
}
}
$X = new Matrix($X);
return ($X->getMatrix(0, $this->n-1, 0, $nx));
} else {
throw new Exception(JAMAError(MatrixRankException));
}
} else {
throw new Exception(JAMAError(MatrixDimensionException));
}
} // function solve()
} // class QRDecomposition
PHPExcel/Shared/JAMA/Matrix.php 0000666 00000110146 15016734321 0012060 0 ustar 00 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
//Square matrix - n x n
case 'integer':
$this->m = $args[0];
$this->n = $args[0];
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0));
break;
//Rectangular matrix - m x n
case 'integer,integer':
$this->m = $args[0];
$this->n = $args[1];
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0));
break;
//Rectangular matrix constant-filled - m x n filled with c
case 'integer,integer,integer':
$this->m = $args[0];
$this->n = $args[1];
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2]));
break;
//Rectangular matrix constant-filled - m x n filled with c
case 'integer,integer,double':
$this->m = $args[0];
$this->n = $args[1];
$this->A = array_fill(0, $this->m, array_fill(0, $this->n, $args[2]));
break;
//Rectangular matrix - m x n initialized from 2D array
case 'array':
$this->m = count($args[0]);
$this->n = count($args[0][0]);
$this->A = $args[0];
break;
//Rectangular matrix - m x n initialized from 2D array
case 'array,integer,integer':
$this->m = $args[1];
$this->n = $args[2];
$this->A = $args[0];
break;
//Rectangular matrix - m x n initialized from packed array
case 'array,integer':
$this->m = $args[1];
if ($this->m != 0) {
$this->n = count($args[0]) / $this->m;
} else {
$this->n = 0;
}
if (($this->m * $this->n) == count($args[0])) {
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$this->A[$i][$j] = $args[0][$i + $j * $this->m];
}
}
} else {
throw new Exception(JAMAError(ArrayLengthException));
}
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function __construct()
/**
* getArray
*
* @return array Matrix array
*/
public function getArray() {
return $this->A;
} // function getArray()
/**
* getArrayCopy
*
* @return array Matrix array copy
*/
public function getArrayCopy() {
return $this->A;
} // function getArrayCopy()
/**
* constructWithCopy
* Construct a matrix from a copy of a 2-D array.
*
* @param double A[][] Two-dimensional array of doubles.
* @exception IllegalArgumentException All rows must have the same length
*/
public function constructWithCopy($A) {
$this->m = count($A);
$this->n = count($A[0]);
$newCopyMatrix = new Matrix($this->m, $this->n);
for ($i = 0; $i < $this->m; ++$i) {
if (count($A[$i]) != $this->n) {
throw new Exception(JAMAError(RowLengthException));
}
for ($j = 0; $j < $this->n; ++$j) {
$newCopyMatrix->A[$i][$j] = $A[$i][$j];
}
}
return $newCopyMatrix;
} // function constructWithCopy()
/**
* getColumnPackedCopy
*
* Get a column-packed array
* @return array Column-packed matrix array
*/
public function getColumnPackedCopy() {
$P = array();
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
array_push($P, $this->A[$j][$i]);
}
}
return $P;
} // function getColumnPackedCopy()
/**
* getRowPackedCopy
*
* Get a row-packed array
* @return array Row-packed matrix array
*/
public function getRowPackedCopy() {
$P = array();
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
array_push($P, $this->A[$i][$j]);
}
}
return $P;
} // function getRowPackedCopy()
/**
* getRowDimension
*
* @return int Row dimension
*/
public function getRowDimension() {
return $this->m;
} // function getRowDimension()
/**
* getColumnDimension
*
* @return int Column dimension
*/
public function getColumnDimension() {
return $this->n;
} // function getColumnDimension()
/**
* get
*
* Get the i,j-th element of the matrix.
* @param int $i Row position
* @param int $j Column position
* @return mixed Element (int/float/double)
*/
public function get($i = null, $j = null) {
return $this->A[$i][$j];
} // function get()
/**
* getMatrix
*
* Get a submatrix
* @param int $i0 Initial row index
* @param int $iF Final row index
* @param int $j0 Initial column index
* @param int $jF Final column index
* @return Matrix Submatrix
*/
public function getMatrix() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
//A($i0...; $j0...)
case 'integer,integer':
list($i0, $j0) = $args;
if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m, $n);
for($i = $i0; $i < $this->m; ++$i) {
for($j = $j0; $j < $this->n; ++$j) {
$R->set($i, $j, $this->A[$i][$j]);
}
}
return $R;
break;
//A($i0...$iF; $j0...$jF)
case 'integer,integer,integer,integer':
list($i0, $iF, $j0, $jF) = $args;
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m+1, $n+1);
for($i = $i0; $i <= $iF; ++$i) {
for($j = $j0; $j <= $jF; ++$j) {
$R->set($i - $i0, $j - $j0, $this->A[$i][$j]);
}
}
return $R;
break;
//$R = array of row indices; $C = array of column indices
case 'array,array':
list($RL, $CL) = $args;
if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m, $n);
for($i = 0; $i < $m; ++$i) {
for($j = 0; $j < $n; ++$j) {
$R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]);
}
}
return $R;
break;
//$RL = array of row indices; $CL = array of column indices
case 'array,array':
list($RL, $CL) = $args;
if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m, $n);
for($i = 0; $i < $m; ++$i) {
for($j = 0; $j < $n; ++$j) {
$R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]);
}
}
return $R;
break;
//A($i0...$iF); $CL = array of column indices
case 'integer,integer,array':
list($i0, $iF, $CL) = $args;
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m, $n);
for($i = $i0; $i < $iF; ++$i) {
for($j = 0; $j < $n; ++$j) {
$R->set($i - $i0, $j, $this->A[$RL[$i]][$j]);
}
}
return $R;
break;
//$RL = array of row indices
case 'array,integer,integer':
list($RL, $j0, $jF) = $args;
if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
$R = new Matrix($m, $n+1);
for($i = 0; $i < $m; ++$i) {
for($j = $j0; $j <= $jF; ++$j) {
$R->set($i, $j - $j0, $this->A[$RL[$i]][$j]);
}
}
return $R;
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function getMatrix()
/**
* setMatrix
*
* Set a submatrix
* @param int $i0 Initial row index
* @param int $j0 Initial column index
* @param mixed $S Matrix/Array submatrix
* ($i0, $j0, $S) $S = Matrix
* ($i0, $j0, $S) $S = Array
*/
public function setMatrix() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'integer,integer,object':
if ($args[2] instanceof Matrix) { $M = $args[2]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
if (($args[0] + $M->m) <= $this->m) { $i0 = $args[0]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (($args[1] + $M->n) <= $this->n) { $j0 = $args[1]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
for($i = $i0; $i < $i0 + $M->m; ++$i) {
for($j = $j0; $j < $j0 + $M->n; ++$j) {
$this->A[$i][$j] = $M->get($i - $i0, $j - $j0);
}
}
break;
case 'integer,integer,array':
$M = new Matrix($args[2]);
if (($args[0] + $M->m) <= $this->m) { $i0 = $args[0]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
if (($args[1] + $M->n) <= $this->n) { $j0 = $args[1]; } else { throw new Exception(JAMAError(ArgumentBoundsException)); }
for($i = $i0; $i < $i0 + $M->m; ++$i) {
for($j = $j0; $j < $j0 + $M->n; ++$j) {
$this->A[$i][$j] = $M->get($i - $i0, $j - $j0);
}
}
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function setMatrix()
/**
* checkMatrixDimensions
*
* Is matrix B the same size?
* @param Matrix $B Matrix B
* @return boolean
*/
public function checkMatrixDimensions($B = null) {
if ($B instanceof Matrix) {
if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) {
return true;
} else {
throw new Exception(JAMAError(MatrixDimensionException));
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function checkMatrixDimensions()
/**
* set
*
* Set the i,j-th element of the matrix.
* @param int $i Row position
* @param int $j Column position
* @param mixed $c Int/float/double value
* @return mixed Element (int/float/double)
*/
public function set($i = null, $j = null, $c = null) {
// Optimized set version just has this
$this->A[$i][$j] = $c;
/*
if (is_int($i) && is_int($j) && is_numeric($c)) {
if (($i < $this->m) && ($j < $this->n)) {
$this->A[$i][$j] = $c;
} else {
echo "A[$i][$j] = $c
";
throw new Exception(JAMAError(ArgumentBoundsException));
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
*/
} // function set()
/**
* identity
*
* Generate an identity matrix.
* @param int $m Row dimension
* @param int $n Column dimension
* @return Matrix Identity matrix
*/
public function identity($m = null, $n = null) {
return $this->diagonal($m, $n, 1);
} // function identity()
/**
* diagonal
*
* Generate a diagonal matrix
* @param int $m Row dimension
* @param int $n Column dimension
* @param mixed $c Diagonal value
* @return Matrix Diagonal matrix
*/
public function diagonal($m = null, $n = null, $c = 1) {
$R = new Matrix($m, $n);
for($i = 0; $i < $m; ++$i) {
$R->set($i, $i, $c);
}
return $R;
} // function diagonal()
/**
* filled
*
* Generate a filled matrix
* @param int $m Row dimension
* @param int $n Column dimension
* @param int $c Fill constant
* @return Matrix Filled matrix
*/
public function filled($m = null, $n = null, $c = 0) {
if (is_int($m) && is_int($n) && is_numeric($c)) {
$R = new Matrix($m, $n, $c);
return $R;
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function filled()
/**
* random
*
* Generate a random matrix
* @param int $m Row dimension
* @param int $n Column dimension
* @return Matrix Random matrix
*/
public function random($m = null, $n = null, $a = RAND_MIN, $b = RAND_MAX) {
if (is_int($m) && is_int($n) && is_numeric($a) && is_numeric($b)) {
$R = new Matrix($m, $n);
for($i = 0; $i < $m; ++$i) {
for($j = 0; $j < $n; ++$j) {
$R->set($i, $j, mt_rand($a, $b));
}
}
return $R;
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function random()
/**
* packed
*
* Alias for getRowPacked
* @return array Packed array
*/
public function packed() {
return $this->getRowPacked();
} // function packed()
/**
* getMatrixByRow
*
* Get a submatrix by row index/range
* @param int $i0 Initial row index
* @param int $iF Final row index
* @return Matrix Submatrix
*/
public function getMatrixByRow($i0 = null, $iF = null) {
if (is_int($i0)) {
if (is_int($iF)) {
return $this->getMatrix($i0, 0, $iF + 1, $this->n);
} else {
return $this->getMatrix($i0, 0, $i0 + 1, $this->n);
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function getMatrixByRow()
/**
* getMatrixByCol
*
* Get a submatrix by column index/range
* @param int $i0 Initial column index
* @param int $iF Final column index
* @return Matrix Submatrix
*/
public function getMatrixByCol($j0 = null, $jF = null) {
if (is_int($j0)) {
if (is_int($jF)) {
return $this->getMatrix(0, $j0, $this->m, $jF + 1);
} else {
return $this->getMatrix(0, $j0, $this->m, $j0 + 1);
}
} else {
throw new Exception(JAMAError(ArgumentTypeException));
}
} // function getMatrixByCol()
/**
* transpose
*
* Tranpose matrix
* @return Matrix Transposed matrix
*/
public function transpose() {
$R = new Matrix($this->n, $this->m);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$R->set($j, $i, $this->A[$i][$j]);
}
}
return $R;
} // function transpose()
/**
* norm1
*
* One norm
* @return float Maximum column sum
*/
public function norm1() {
$r = 0;
for($j = 0; $j < $this->n; ++$j) {
$s = 0;
for($i = 0; $i < $this->m; ++$i) {
$s += abs($this->A[$i][$j]);
}
$r = ($r > $s) ? $r : $s;
}
return $r;
} // function norm1()
/**
* norm2
*
* Maximum singular value
* @return float Maximum singular value
*/
public function norm2() {
} // function norm2()
/**
* normInf
*
* Infinite norm
* @return float Maximum row sum
*/
public function normInf() {
$r = 0;
for($i = 0; $i < $this->m; ++$i) {
$s = 0;
for($j = 0; $j < $this->n; ++$j) {
$s += abs($this->A[$i][$j]);
}
$r = ($r > $s) ? $r : $s;
}
return $r;
} // function normInf()
/**
* normF
*
* Frobenius norm
* @return float Square root of the sum of all elements squared
*/
public function normF() {
$f = 0;
for ($i = 0; $i < $this->m; ++$i) {
for ($j = 0; $j < $this->n; ++$j) {
$f = hypo($f,$this->A[$i][$j]);
}
}
return $f;
} // function normF()
/**
* Matrix rank
*
* @return effective numerical rank, obtained from SVD.
*/
public function rank () {
$svd = new SingularValueDecomposition($this);
return $svd->rank();
} // function rank ()
/**
* Matrix condition (2 norm)
*
* @return ratio of largest to smallest singular value.
*/
public function cond () {
$svd = new SingularValueDecomposition($this);
return $svd->cond();
} // function cond ()
/**
* trace
*
* Sum of diagonal elements
* @return float Sum of diagonal elements
*/
public function trace() {
$s = 0;
$n = min($this->m, $this->n);
for($i = 0; $i < $n; ++$i) {
$s += $this->A[$i][$i];
}
return $s;
} // function trace()
/**
* uminus
*
* Unary minus matrix -A
* @return Matrix Unary minus matrix
*/
public function uminus() {
} // function uminus()
/**
* plus
*
* A + B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function plus() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]);
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function plus()
/**
* plusEquals
*
* A = A + B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function plusEquals() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$validValues = True;
$value = $M->get($i, $j);
if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) {
$this->A[$i][$j] = trim($this->A[$i][$j],'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
}
if ((is_string($value)) && (!is_numeric($value))) {
$value = trim($value,'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
}
if ($validValues) {
$this->A[$i][$j] += $value;
} else {
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
}
}
}
return $this;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function plusEquals()
/**
* minus
*
* A - B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function minus() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]);
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function minus()
/**
* minusEquals
*
* A = A - B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function minusEquals() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$validValues = True;
$value = $M->get($i, $j);
if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) {
$this->A[$i][$j] = trim($this->A[$i][$j],'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
}
if ((is_string($value)) && (!is_numeric($value))) {
$value = trim($value,'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
}
if ($validValues) {
$this->A[$i][$j] -= $value;
} else {
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
}
}
}
return $this;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function minusEquals()
/**
* arrayTimes
*
* Element-by-element multiplication
* Cij = Aij * Bij
* @param mixed $B Matrix/Array
* @return Matrix Matrix Cij
*/
public function arrayTimes() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]);
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayTimes()
/**
* arrayTimesEquals
*
* Element-by-element multiplication
* Aij = Aij * Bij
* @param mixed $B Matrix/Array
* @return Matrix Matrix Aij
*/
public function arrayTimesEquals() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$validValues = True;
$value = $M->get($i, $j);
if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) {
$this->A[$i][$j] = trim($this->A[$i][$j],'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
}
if ((is_string($value)) && (!is_numeric($value))) {
$value = trim($value,'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
}
if ($validValues) {
$this->A[$i][$j] *= $value;
} else {
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
}
}
}
return $this;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayTimesEquals()
/**
* arrayRightDivide
*
* Element-by-element right division
* A / B
* @param Matrix $B Matrix B
* @return Matrix Division result
*/
public function arrayRightDivide() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$validValues = True;
$value = $M->get($i, $j);
if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) {
$this->A[$i][$j] = trim($this->A[$i][$j],'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
}
if ((is_string($value)) && (!is_numeric($value))) {
$value = trim($value,'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
}
if ($validValues) {
if ($value == 0) {
// Trap for Divide by Zero error
$M->set($i, $j, '#DIV/0!');
} else {
$M->set($i, $j, $this->A[$i][$j] / $value);
}
} else {
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
}
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayRightDivide()
/**
* arrayRightDivideEquals
*
* Element-by-element right division
* Aij = Aij / Bij
* @param mixed $B Matrix/Array
* @return Matrix Matrix Aij
*/
public function arrayRightDivideEquals() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j);
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayRightDivideEquals()
/**
* arrayLeftDivide
*
* Element-by-element Left division
* A / B
* @param Matrix $B Matrix B
* @return Matrix Division result
*/
public function arrayLeftDivide() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]);
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayLeftDivide()
/**
* arrayLeftDivideEquals
*
* Element-by-element Left division
* Aij = Aij / Bij
* @param mixed $B Matrix/Array
* @return Matrix Matrix Aij
*/
public function arrayLeftDivideEquals() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j];
}
}
return $M;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function arrayLeftDivideEquals()
/**
* times
*
* Matrix multiplication
* @param mixed $n Matrix/Array/Scalar
* @return Matrix Product
*/
public function times() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $B = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
if ($this->n == $B->m) {
$C = new Matrix($this->m, $B->n);
for($j = 0; $j < $B->n; ++$j) {
for ($k = 0; $k < $this->n; ++$k) {
$Bcolj[$k] = $B->A[$k][$j];
}
for($i = 0; $i < $this->m; ++$i) {
$Arowi = $this->A[$i];
$s = 0;
for($k = 0; $k < $this->n; ++$k) {
$s += $Arowi[$k] * $Bcolj[$k];
}
$C->A[$i][$j] = $s;
}
}
return $C;
} else {
throw new Exception(JAMAError(MatrixDimensionMismatch));
}
break;
case 'array':
$B = new Matrix($args[0]);
if ($this->n == $B->m) {
$C = new Matrix($this->m, $B->n);
for($i = 0; $i < $C->m; ++$i) {
for($j = 0; $j < $C->n; ++$j) {
$s = "0";
for($k = 0; $k < $C->n; ++$k) {
$s += $this->A[$i][$k] * $B->A[$k][$j];
}
$C->A[$i][$j] = $s;
}
}
return $C;
} else {
throw new Exception(JAMAError(MatrixDimensionMismatch));
}
return $M;
break;
case 'integer':
$C = new Matrix($this->A);
for($i = 0; $i < $C->m; ++$i) {
for($j = 0; $j < $C->n; ++$j) {
$C->A[$i][$j] *= $args[0];
}
}
return $C;
break;
case 'double':
$C = new Matrix($this->m, $this->n);
for($i = 0; $i < $C->m; ++$i) {
for($j = 0; $j < $C->n; ++$j) {
$C->A[$i][$j] = $args[0] * $this->A[$i][$j];
}
}
return $C;
break;
case 'float':
$C = new Matrix($this->A);
for($i = 0; $i < $C->m; ++$i) {
for($j = 0; $j < $C->n; ++$j) {
$C->A[$i][$j] *= $args[0];
}
}
return $C;
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
} else {
throw new Exception(PolymorphicArgumentException);
}
} // function times()
/**
* power
*
* A = A ^ B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function power() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
break;
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
$validValues = True;
$value = $M->get($i, $j);
if ((is_string($this->A[$i][$j])) && (!is_numeric($this->A[$i][$j]))) {
$this->A[$i][$j] = trim($this->A[$i][$j],'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
}
if ((is_string($value)) && (!is_numeric($value))) {
$value = trim($value,'"');
$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
}
if ($validValues) {
$this->A[$i][$j] = pow($this->A[$i][$j],$value);
} else {
$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
}
}
}
return $this;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function power()
/**
* concat
*
* A = A & B
* @param mixed $B Matrix/Array
* @return Matrix Sum
*/
public function concat() {
if (func_num_args() > 0) {
$args = func_get_args();
$match = implode(",", array_map('gettype', $args));
switch($match) {
case 'object':
if ($args[0] instanceof Matrix) { $M = $args[0]; } else { throw new Exception(JAMAError(ArgumentTypeException)); }
case 'array':
$M = new Matrix($args[0]);
break;
default:
throw new Exception(JAMAError(PolymorphicArgumentException));
break;
}
$this->checkMatrixDimensions($M);
for($i = 0; $i < $this->m; ++$i) {
for($j = 0; $j < $this->n; ++$j) {
// $this->A[$i][$j] = '"'.trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"').'"';
$this->A[$i][$j] = trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"');
}
}
return $this;
} else {
throw new Exception(JAMAError(PolymorphicArgumentException));
}
} // function concat()
/**
* chol
*
* Cholesky decomposition
* @return Matrix Cholesky decomposition
*/
public function chol() {
return new CholeskyDecomposition($this);
} // function chol()
/**
* lu
*
* LU decomposition
* @return Matrix LU decomposition
*/
public function lu() {
return new LUDecomposition($this);
} // function lu()
/**
* qr
*
* QR decomposition
* @return Matrix QR decomposition
*/
public function qr() {
return new QRDecomposition($this);
} // function qr()
/**
* eig
*
* Eigenvalue decomposition
* @return Matrix Eigenvalue decomposition
*/
public function eig() {
return new EigenvalueDecomposition($this);
} // function eig()
/**
* svd
*
* Singular value decomposition
* @return Singular value decomposition
*/
public function svd() {
return new SingularValueDecomposition($this);
} // function svd()
/**
* 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 LUDecomposition($this);
return $LU->solve($B);
} else {
$QR = new QRDecomposition($this);
return $QR->solve($B);
}
} // function solve()
/**
* Matrix inverse or pseudoinverse.
*
* @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise.
*/
public function inverse() {
return $this->solve($this->identity($this->m, $this->m));
} // function inverse()
/**
* det
*
* Calculate determinant
* @return float Determinant
*/
public function det() {
$L = new LUDecomposition($this);
return $L->det();
} // function det()
/**
* Older debugging utility for backwards compatability.
*
* @return html version of matrix
*/
public function mprint($A, $format="%01.2f", $width=2) {
$m = count($A);
$n = count($A[0]);
$spacing = str_repeat(' ',$width);
for ($i = 0; $i < $m; ++$i) {
for ($j = 0; $j < $n; ++$j) {
$formatted = sprintf($format, $A[$i][$j]);
echo $formatted.$spacing;
}
echo "
";
}
} // function mprint()
/**
* Debugging utility.
*
* @return Output HTML representation of matrix
*/
public function toHTML($width=2) {
print('');
for($i = 0; $i < $this->m; ++$i) {
print('');
for($j = 0; $j < $this->n; ++$j) {
print('' . $this->A[$i][$j] . ' | ');
}
print('
');
}
print('
');
} // function toHTML()
} // class Matrix
PHPExcel/Shared/JAMA/docs/index.php 0000666 00000002301 15016734321 0012644 0 ustar 00
JAMA is a proposed standard matrix class for Java. The JAMA introduction
describes "JAMA : A Java Matrix Package" in this way:
JAMA is a basic linear algebra package for Java. It provides user-level classes for
constructing and manipulating real, dense matrices. It is meant to provide sufficient
functionality for routine problems, packaged in a way that is natural and understandable
to non-experts. It is intended to serve as the standard matrix class for Java, and
will be proposed as such to the Java Grande Forum and then to Sun. A straightforward
public-domain reference implementation has been developed by the MathWorks and NIST as
a strawman for such a class. We are releasing this version in order to obtain public
comment. There is no guarantee that future versions of JAMA will be compatible with this one.
The development team below has successfully ported the JAMA API to PHP. You can explore
this site to learn more about this project and it's current development status.