PageRenderTime 51ms CodeModel.GetById 10ms app.highlight 34ms RepoModel.GetById 2ms app.codeStats 0ms

/PHPExcel/Shared/JAMA/Matrix.php

https://bitbucket.org/nfredricks/wp-employee-time
PHP | 1059 lines | 704 code | 88 blank | 267 comment | 218 complexity | a3929a1a862e4cbf4cb64b35d47ee4c9 MD5 | raw file
   1<?php
   2/**
   3 * @package JAMA
   4 */
   5
   6/** PHPExcel root directory */
   7if (!defined('PHPEXCEL_ROOT')) {
   8	/**
   9	 * @ignore
  10	 */
  11	define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../');
  12	require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  13}
  14
  15
  16/*
  17 *	Matrix class
  18 *
  19 *	@author Paul Meagher
  20 *	@author Michael Bommarito
  21 *	@author Lukasz Karapuda
  22 *	@author Bartek Matosiuk
  23 *	@version 1.8
  24 *	@license PHP v3.0
  25 *	@see http://math.nist.gov/javanumerics/jama/
  26 */
  27class PHPExcel_Shared_JAMA_Matrix {
  28
  29
  30	const PolymorphicArgumentException	= "Invalid argument pattern for polymorphic function.";
  31	const ArgumentTypeException			= "Invalid argument type.";
  32	const ArgumentBoundsException		= "Invalid argument range.";
  33	const MatrixDimensionException		= "Matrix dimensions are not equal.";
  34	const ArrayLengthException			= "Array length must be a multiple of m.";
  35
  36	/**
  37	 *	Matrix storage
  38	 *
  39	 *	@var array
  40	 *	@access public
  41	 */
  42	public $A = array();
  43
  44	/**
  45	 *	Matrix row dimension
  46	 *
  47	 *	@var int
  48	 *	@access private
  49	 */
  50	private $m;
  51
  52	/**
  53	 *	Matrix column dimension
  54	 *
  55	 *	@var int
  56	 *	@access private
  57	 */
  58	private $n;
  59
  60
  61	/**
  62	 *	Polymorphic constructor
  63	 *
  64	 *	As PHP has no support for polymorphic constructors, we hack our own sort of polymorphism using func_num_args, func_get_arg, and gettype. In essence, we're just implementing a simple RTTI filter and calling the appropriate constructor.
  65	 */
  66	public function __construct() {
  67		if (func_num_args() > 0) {
  68			$args = func_get_args();
  69			$match = implode(",", array_map('gettype', $args));
  70
  71			switch($match) {
  72				//Rectangular matrix - m x n initialized from 2D array
  73				case 'array':
  74						$this->m = count($args[0]);
  75						$this->n = count($args[0][0]);
  76						$this->A = $args[0];
  77						break;
  78				//Square matrix - n x n
  79				case 'integer':
  80						$this->m = $args[0];
  81						$this->n = $args[0];
  82						$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0));
  83						break;
  84				//Rectangular matrix - m x n
  85				case 'integer,integer':
  86						$this->m = $args[0];
  87						$this->n = $args[1];
  88						$this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0));
  89						break;
  90				//Rectangular matrix - m x n initialized from packed array
  91				case 'array,integer':
  92						$this->m = $args[1];
  93						if ($this->m != 0) {
  94							$this->n = count($args[0]) / $this->m;
  95						} else {
  96							$this->n = 0;
  97						}
  98						if (($this->m * $this->n) == count($args[0])) {
  99							for($i = 0; $i < $this->m; ++$i) {
 100								for($j = 0; $j < $this->n; ++$j) {
 101									$this->A[$i][$j] = $args[0][$i + $j * $this->m];
 102								}
 103							}
 104						} else {
 105							throw new Exception(self::ArrayLengthException);
 106						}
 107						break;
 108				default:
 109						throw new Exception(self::PolymorphicArgumentException);
 110						break;
 111			}
 112		} else {
 113			throw new Exception(self::PolymorphicArgumentException);
 114		}
 115	}	//	function __construct()
 116
 117
 118	/**
 119	 *	getArray
 120	 *
 121	 *	@return array Matrix array
 122	 */
 123	public function getArray() {
 124		return $this->A;
 125	}	//	function getArray()
 126
 127
 128	/**
 129	 *	getRowDimension
 130	 *
 131	 *	@return int Row dimension
 132	 */
 133	public function getRowDimension() {
 134		return $this->m;
 135	}	//	function getRowDimension()
 136
 137
 138	/**
 139	 *	getColumnDimension
 140	 *
 141	 *	@return int Column dimension
 142	 */
 143	public function getColumnDimension() {
 144		return $this->n;
 145	}	//	function getColumnDimension()
 146
 147
 148	/**
 149	 *	get
 150	 *
 151	 *	Get the i,j-th element of the matrix.
 152	 *	@param int $i Row position
 153	 *	@param int $j Column position
 154	 *	@return mixed Element (int/float/double)
 155	 */
 156	public function get($i = null, $j = null) {
 157		return $this->A[$i][$j];
 158	}	//	function get()
 159
 160
 161	/**
 162	 *	getMatrix
 163	 *
 164	 *	Get a submatrix
 165	 *	@param int $i0 Initial row index
 166	 *	@param int $iF Final row index
 167	 *	@param int $j0 Initial column index
 168	 *	@param int $jF Final column index
 169	 *	@return Matrix Submatrix
 170	 */
 171	public function getMatrix() {
 172		if (func_num_args() > 0) {
 173			$args = func_get_args();
 174			$match = implode(",", array_map('gettype', $args));
 175
 176			switch($match) {
 177				//A($i0...; $j0...)
 178				case 'integer,integer':
 179						list($i0, $j0) = $args;
 180						if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new Exception(self::ArgumentBoundsException); }
 181						if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new Exception(self::ArgumentBoundsException); }
 182						$R = new PHPExcel_Shared_JAMA_Matrix($m, $n);
 183						for($i = $i0; $i < $this->m; ++$i) {
 184							for($j = $j0; $j < $this->n; ++$j) {
 185								$R->set($i, $j, $this->A[$i][$j]);
 186							}
 187						}
 188						return $R;
 189						break;
 190				//A($i0...$iF; $j0...$jF)
 191				case 'integer,integer,integer,integer':
 192						list($i0, $iF, $j0, $jF) = $args;
 193						if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(self::ArgumentBoundsException); }
 194						if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(self::ArgumentBoundsException); }
 195						$R = new PHPExcel_Shared_JAMA_Matrix($m+1, $n+1);
 196						for($i = $i0; $i <= $iF; ++$i) {
 197							for($j = $j0; $j <= $jF; ++$j) {
 198								$R->set($i - $i0, $j - $j0, $this->A[$i][$j]);
 199							}
 200						}
 201						return $R;
 202						break;
 203				//$R = array of row indices; $C = array of column indices
 204				case 'array,array':
 205						list($RL, $CL) = $args;
 206						if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); }
 207						if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); }
 208						$R = new PHPExcel_Shared_JAMA_Matrix($m, $n);
 209						for($i = 0; $i < $m; ++$i) {
 210							for($j = 0; $j < $n; ++$j) {
 211								$R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]);
 212							}
 213						}
 214						return $R;
 215						break;
 216				//$RL = array of row indices; $CL = array of column indices
 217				case 'array,array':
 218						list($RL, $CL) = $args;
 219						if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); }
 220						if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); }
 221						$R = new PHPExcel_Shared_JAMA_Matrix($m, $n);
 222						for($i = 0; $i < $m; ++$i) {
 223							for($j = 0; $j < $n; ++$j) {
 224								$R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]);
 225							}
 226						}
 227						return $R;
 228						break;
 229				//A($i0...$iF); $CL = array of column indices
 230				case 'integer,integer,array':
 231						list($i0, $iF, $CL) = $args;
 232						if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(self::ArgumentBoundsException); }
 233						if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); }
 234						$R = new PHPExcel_Shared_JAMA_Matrix($m, $n);
 235						for($i = $i0; $i < $iF; ++$i) {
 236							for($j = 0; $j < $n; ++$j) {
 237								$R->set($i - $i0, $j, $this->A[$RL[$i]][$j]);
 238							}
 239						}
 240						return $R;
 241						break;
 242				//$RL = array of row indices
 243				case 'array,integer,integer':
 244						list($RL, $j0, $jF) = $args;
 245						if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); }
 246						if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(self::ArgumentBoundsException); }
 247						$R = new PHPExcel_Shared_JAMA_Matrix($m, $n+1);
 248						for($i = 0; $i < $m; ++$i) {
 249							for($j = $j0; $j <= $jF; ++$j) {
 250								$R->set($i, $j - $j0, $this->A[$RL[$i]][$j]);
 251							}
 252						}
 253						return $R;
 254						break;
 255				default:
 256						throw new Exception(self::PolymorphicArgumentException);
 257						break;
 258			}
 259		} else {
 260			throw new Exception(self::PolymorphicArgumentException);
 261		}
 262	}	//	function getMatrix()
 263
 264
 265	/**
 266	 *	checkMatrixDimensions
 267	 *
 268	 *	Is matrix B the same size?
 269	 *	@param Matrix $B Matrix B
 270	 *	@return boolean
 271	 */
 272	public function checkMatrixDimensions($B = null) {
 273		if ($B instanceof PHPExcel_Shared_JAMA_Matrix) {
 274			if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) {
 275				return true;
 276			} else {
 277				throw new Exception(self::MatrixDimensionException);
 278			}
 279		} else {
 280			throw new Exception(self::ArgumentTypeException);
 281		}
 282	}	//	function checkMatrixDimensions()
 283
 284
 285
 286	/**
 287	 *	set
 288	 *
 289	 *	Set the i,j-th element of the matrix.
 290	 *	@param int $i Row position
 291	 *	@param int $j Column position
 292	 *	@param mixed $c Int/float/double value
 293	 *	@return mixed Element (int/float/double)
 294	 */
 295	public function set($i = null, $j = null, $c = null) {
 296		// Optimized set version just has this
 297		$this->A[$i][$j] = $c;
 298	}	//	function set()
 299
 300
 301	/**
 302	 *	identity
 303	 *
 304	 *	Generate an identity matrix.
 305	 *	@param int $m Row dimension
 306	 *	@param int $n Column dimension
 307	 *	@return Matrix Identity matrix
 308	 */
 309	public function identity($m = null, $n = null) {
 310		return $this->diagonal($m, $n, 1);
 311	}	//	function identity()
 312
 313
 314	/**
 315	 *	diagonal
 316	 *
 317	 *	Generate a diagonal matrix
 318	 *	@param int $m Row dimension
 319	 *	@param int $n Column dimension
 320	 *	@param mixed $c Diagonal value
 321	 *	@return Matrix Diagonal matrix
 322	 */
 323	public function diagonal($m = null, $n = null, $c = 1) {
 324		$R = new PHPExcel_Shared_JAMA_Matrix($m, $n);
 325		for($i = 0; $i < $m; ++$i) {
 326			$R->set($i, $i, $c);
 327		}
 328		return $R;
 329	}	//	function diagonal()
 330
 331
 332	/**
 333	 *	getMatrixByRow
 334	 *
 335	 *	Get a submatrix by row index/range
 336	 *	@param int $i0 Initial row index
 337	 *	@param int $iF Final row index
 338	 *	@return Matrix Submatrix
 339	 */
 340	public function getMatrixByRow($i0 = null, $iF = null) {
 341		if (is_int($i0)) {
 342			if (is_int($iF)) {
 343				return $this->getMatrix($i0, 0, $iF + 1, $this->n);
 344			} else {
 345				return $this->getMatrix($i0, 0, $i0 + 1, $this->n);
 346			}
 347		} else {
 348			throw new Exception(self::ArgumentTypeException);
 349		}
 350	}	//	function getMatrixByRow()
 351
 352
 353	/**
 354	 *	getMatrixByCol
 355	 *
 356	 *	Get a submatrix by column index/range
 357	 *	@param int $i0 Initial column index
 358	 *	@param int $iF Final column index
 359	 *	@return Matrix Submatrix
 360	 */
 361	public function getMatrixByCol($j0 = null, $jF = null) {
 362		if (is_int($j0)) {
 363			if (is_int($jF)) {
 364				return $this->getMatrix(0, $j0, $this->m, $jF + 1);
 365			} else {
 366				return $this->getMatrix(0, $j0, $this->m, $j0 + 1);
 367			}
 368		} else {
 369			throw new Exception(self::ArgumentTypeException);
 370		}
 371	}	//	function getMatrixByCol()
 372
 373
 374	/**
 375	 *	transpose
 376	 *
 377	 *	Tranpose matrix
 378	 *	@return Matrix Transposed matrix
 379	 */
 380	public function transpose() {
 381		$R = new PHPExcel_Shared_JAMA_Matrix($this->n, $this->m);
 382		for($i = 0; $i < $this->m; ++$i) {
 383			for($j = 0; $j < $this->n; ++$j) {
 384				$R->set($j, $i, $this->A[$i][$j]);
 385			}
 386		}
 387		return $R;
 388	}	//	function transpose()
 389
 390
 391	/**
 392	 *	trace
 393	 *
 394	 *	Sum of diagonal elements
 395	 *	@return float Sum of diagonal elements
 396	 */
 397	public function trace() {
 398		$s = 0;
 399		$n = min($this->m, $this->n);
 400		for($i = 0; $i < $n; ++$i) {
 401			$s += $this->A[$i][$i];
 402		}
 403		return $s;
 404	}	//	function trace()
 405
 406
 407	/**
 408	 *	uminus
 409	 *
 410	 *	Unary minus matrix -A
 411	 *	@return Matrix Unary minus matrix
 412	 */
 413	public function uminus() {
 414	}	//	function uminus()
 415
 416
 417	/**
 418	 *	plus
 419	 *
 420	 *	A + B
 421	 *	@param mixed $B Matrix/Array
 422	 *	@return Matrix Sum
 423	 */
 424	public function plus() {
 425		if (func_num_args() > 0) {
 426			$args = func_get_args();
 427			$match = implode(",", array_map('gettype', $args));
 428
 429			switch($match) {
 430				case 'object':
 431						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 432						break;
 433				case 'array':
 434						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 435						break;
 436				default:
 437						throw new Exception(self::PolymorphicArgumentException);
 438						break;
 439			}
 440			$this->checkMatrixDimensions($M);
 441			for($i = 0; $i < $this->m; ++$i) {
 442				for($j = 0; $j < $this->n; ++$j) {
 443					$M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]);
 444				}
 445			}
 446			return $M;
 447		} else {
 448			throw new Exception(self::PolymorphicArgumentException);
 449		}
 450	}	//	function plus()
 451
 452
 453	/**
 454	 *	plusEquals
 455	 *
 456	 *	A = A + B
 457	 *	@param mixed $B Matrix/Array
 458	 *	@return Matrix Sum
 459	 */
 460	public function plusEquals() {
 461		if (func_num_args() > 0) {
 462			$args = func_get_args();
 463			$match = implode(",", array_map('gettype', $args));
 464
 465			switch($match) {
 466				case 'object':
 467						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 468						break;
 469				case 'array':
 470						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 471						break;
 472				default:
 473						throw new Exception(self::PolymorphicArgumentException);
 474						break;
 475			}
 476			$this->checkMatrixDimensions($M);
 477			for($i = 0; $i < $this->m; ++$i) {
 478				for($j = 0; $j < $this->n; ++$j) {
 479					$validValues = True;
 480					$value = $M->get($i, $j);
 481					if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) {
 482						$this->A[$i][$j] = trim($this->A[$i][$j],'"');
 483						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
 484					}
 485					if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) {
 486						$value = trim($value,'"');
 487						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
 488					}
 489					if ($validValues) {
 490						$this->A[$i][$j] += $value;
 491					} else {
 492						$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
 493					}
 494				}
 495			}
 496			return $this;
 497		} else {
 498			throw new Exception(self::PolymorphicArgumentException);
 499		}
 500	}	//	function plusEquals()
 501
 502
 503	/**
 504	 *	minus
 505	 *
 506	 *	A - B
 507	 *	@param mixed $B Matrix/Array
 508	 *	@return Matrix Sum
 509	 */
 510	public function minus() {
 511		if (func_num_args() > 0) {
 512			$args = func_get_args();
 513			$match = implode(",", array_map('gettype', $args));
 514
 515			switch($match) {
 516				case 'object':
 517						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 518						break;
 519				case 'array':
 520						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 521						break;
 522				default:
 523						throw new Exception(self::PolymorphicArgumentException);
 524						break;
 525			}
 526			$this->checkMatrixDimensions($M);
 527			for($i = 0; $i < $this->m; ++$i) {
 528				for($j = 0; $j < $this->n; ++$j) {
 529					$M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]);
 530				}
 531			}
 532			return $M;
 533		} else {
 534			throw new Exception(self::PolymorphicArgumentException);
 535		}
 536	}	//	function minus()
 537
 538
 539	/**
 540	 *	minusEquals
 541	 *
 542	 *	A = A - B
 543	 *	@param mixed $B Matrix/Array
 544	 *	@return Matrix Sum
 545	 */
 546	public function minusEquals() {
 547		if (func_num_args() > 0) {
 548			$args = func_get_args();
 549			$match = implode(",", array_map('gettype', $args));
 550
 551			switch($match) {
 552				case 'object':
 553						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 554						break;
 555				case 'array':
 556						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 557						break;
 558				default:
 559						throw new Exception(self::PolymorphicArgumentException);
 560						break;
 561			}
 562			$this->checkMatrixDimensions($M);
 563			for($i = 0; $i < $this->m; ++$i) {
 564				for($j = 0; $j < $this->n; ++$j) {
 565					$validValues = True;
 566					$value = $M->get($i, $j);
 567					if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) {
 568						$this->A[$i][$j] = trim($this->A[$i][$j],'"');
 569						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
 570					}
 571					if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) {
 572						$value = trim($value,'"');
 573						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
 574					}
 575					if ($validValues) {
 576						$this->A[$i][$j] -= $value;
 577					} else {
 578						$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
 579					}
 580				}
 581			}
 582			return $this;
 583		} else {
 584			throw new Exception(self::PolymorphicArgumentException);
 585		}
 586	}	//	function minusEquals()
 587
 588
 589	/**
 590	 *	arrayTimes
 591	 *
 592	 *	Element-by-element multiplication
 593	 *	Cij = Aij * Bij
 594	 *	@param mixed $B Matrix/Array
 595	 *	@return Matrix Matrix Cij
 596	 */
 597	public function arrayTimes() {
 598		if (func_num_args() > 0) {
 599			$args = func_get_args();
 600			$match = implode(",", array_map('gettype', $args));
 601
 602			switch($match) {
 603				case 'object':
 604						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 605						break;
 606				case 'array':
 607						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 608						break;
 609				default:
 610						throw new Exception(self::PolymorphicArgumentException);
 611						break;
 612			}
 613			$this->checkMatrixDimensions($M);
 614			for($i = 0; $i < $this->m; ++$i) {
 615				for($j = 0; $j < $this->n; ++$j) {
 616					$M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]);
 617				}
 618			}
 619			return $M;
 620		} else {
 621			throw new Exception(self::PolymorphicArgumentException);
 622		}
 623	}	//	function arrayTimes()
 624
 625
 626	/**
 627	 *	arrayTimesEquals
 628	 *
 629	 *	Element-by-element multiplication
 630	 *	Aij = Aij * Bij
 631	 *	@param mixed $B Matrix/Array
 632	 *	@return Matrix Matrix Aij
 633	 */
 634	public function arrayTimesEquals() {
 635		if (func_num_args() > 0) {
 636			$args = func_get_args();
 637			$match = implode(",", array_map('gettype', $args));
 638
 639			switch($match) {
 640				case 'object':
 641						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 642						break;
 643				case 'array':
 644						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 645						break;
 646				default:
 647						throw new Exception(self::PolymorphicArgumentException);
 648						break;
 649			}
 650			$this->checkMatrixDimensions($M);
 651			for($i = 0; $i < $this->m; ++$i) {
 652				for($j = 0; $j < $this->n; ++$j) {
 653					$validValues = True;
 654					$value = $M->get($i, $j);
 655					if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) {
 656						$this->A[$i][$j] = trim($this->A[$i][$j],'"');
 657						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
 658					}
 659					if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) {
 660						$value = trim($value,'"');
 661						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
 662					}
 663					if ($validValues) {
 664						$this->A[$i][$j] *= $value;
 665					} else {
 666						$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
 667					}
 668				}
 669			}
 670			return $this;
 671		} else {
 672			throw new Exception(self::PolymorphicArgumentException);
 673		}
 674	}	//	function arrayTimesEquals()
 675
 676
 677	/**
 678	 *	arrayRightDivide
 679	 *
 680	 *	Element-by-element right division
 681	 *	A / B
 682	 *	@param Matrix $B Matrix B
 683	 *	@return Matrix Division result
 684	 */
 685	public function arrayRightDivide() {
 686		if (func_num_args() > 0) {
 687			$args = func_get_args();
 688			$match = implode(",", array_map('gettype', $args));
 689
 690			switch($match) {
 691				case 'object':
 692						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 693						break;
 694				case 'array':
 695						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 696						break;
 697				default:
 698						throw new Exception(self::PolymorphicArgumentException);
 699						break;
 700			}
 701			$this->checkMatrixDimensions($M);
 702			for($i = 0; $i < $this->m; ++$i) {
 703				for($j = 0; $j < $this->n; ++$j) {
 704					$validValues = True;
 705					$value = $M->get($i, $j);
 706					if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) {
 707						$this->A[$i][$j] = trim($this->A[$i][$j],'"');
 708						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
 709					}
 710					if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) {
 711						$value = trim($value,'"');
 712						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
 713					}
 714					if ($validValues) {
 715						if ($value == 0) {
 716							//	Trap for Divide by Zero error
 717							$M->set($i, $j, '#DIV/0!');
 718						} else {
 719							$M->set($i, $j, $this->A[$i][$j] / $value);
 720						}
 721					} else {
 722						$M->set($i, $j, PHPExcel_Calculation_Functions::NaN());
 723					}
 724				}
 725			}
 726			return $M;
 727		} else {
 728			throw new Exception(self::PolymorphicArgumentException);
 729		}
 730	}	//	function arrayRightDivide()
 731
 732
 733	/**
 734	 *	arrayRightDivideEquals
 735	 *
 736	 *	Element-by-element right division
 737	 *	Aij = Aij / Bij
 738	 *	@param mixed $B Matrix/Array
 739	 *	@return Matrix Matrix Aij
 740	 */
 741	public function arrayRightDivideEquals() {
 742		if (func_num_args() > 0) {
 743			$args = func_get_args();
 744			$match = implode(",", array_map('gettype', $args));
 745
 746			switch($match) {
 747				case 'object':
 748						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 749						break;
 750				case 'array':
 751						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 752						break;
 753				default:
 754						throw new Exception(self::PolymorphicArgumentException);
 755						break;
 756			}
 757			$this->checkMatrixDimensions($M);
 758			for($i = 0; $i < $this->m; ++$i) {
 759				for($j = 0; $j < $this->n; ++$j) {
 760					$this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j);
 761				}
 762			}
 763			return $M;
 764		} else {
 765			throw new Exception(self::PolymorphicArgumentException);
 766		}
 767	}	//	function arrayRightDivideEquals()
 768
 769
 770	/**
 771	 *	arrayLeftDivide
 772	 *
 773	 *	Element-by-element Left division
 774	 *	A / B
 775	 *	@param Matrix $B Matrix B
 776	 *	@return Matrix Division result
 777	 */
 778	public function arrayLeftDivide() {
 779		if (func_num_args() > 0) {
 780			$args = func_get_args();
 781			$match = implode(",", array_map('gettype', $args));
 782
 783			switch($match) {
 784				case 'object':
 785						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 786						break;
 787				case 'array':
 788						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 789						break;
 790				default:
 791						throw new Exception(self::PolymorphicArgumentException);
 792						break;
 793			}
 794			$this->checkMatrixDimensions($M);
 795			for($i = 0; $i < $this->m; ++$i) {
 796				for($j = 0; $j < $this->n; ++$j) {
 797					$M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]);
 798				}
 799			}
 800			return $M;
 801		} else {
 802			throw new Exception(self::PolymorphicArgumentException);
 803		}
 804	}	//	function arrayLeftDivide()
 805
 806
 807	/**
 808	 *	arrayLeftDivideEquals
 809	 *
 810	 *	Element-by-element Left division
 811	 *	Aij = Aij / Bij
 812	 *	@param mixed $B Matrix/Array
 813	 *	@return Matrix Matrix Aij
 814	 */
 815	public function arrayLeftDivideEquals() {
 816		if (func_num_args() > 0) {
 817			$args = func_get_args();
 818			$match = implode(",", array_map('gettype', $args));
 819
 820			switch($match) {
 821				case 'object':
 822						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 823						break;
 824				case 'array':
 825						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 826						break;
 827				default:
 828						throw new Exception(self::PolymorphicArgumentException);
 829						break;
 830			}
 831			$this->checkMatrixDimensions($M);
 832			for($i = 0; $i < $this->m; ++$i) {
 833				for($j = 0; $j < $this->n; ++$j) {
 834					$this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j];
 835				}
 836			}
 837			return $M;
 838		} else {
 839			throw new Exception(self::PolymorphicArgumentException);
 840		}
 841	}	//	function arrayLeftDivideEquals()
 842
 843
 844	/**
 845	 *	times
 846	 *
 847	 *	Matrix multiplication
 848	 *	@param mixed $n Matrix/Array/Scalar
 849	 *	@return Matrix Product
 850	 */
 851	public function times() {
 852		if (func_num_args() > 0) {
 853			$args  = func_get_args();
 854			$match = implode(",", array_map('gettype', $args));
 855
 856			switch($match) {
 857				case 'object':
 858						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $B = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 859						if ($this->n == $B->m) {
 860							$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n);
 861							for($j = 0; $j < $B->n; ++$j) {
 862								for ($k = 0; $k < $this->n; ++$k) {
 863									$Bcolj[$k] = $B->A[$k][$j];
 864								}
 865								for($i = 0; $i < $this->m; ++$i) {
 866									$Arowi = $this->A[$i];
 867									$s = 0;
 868									for($k = 0; $k < $this->n; ++$k) {
 869										$s += $Arowi[$k] * $Bcolj[$k];
 870									}
 871									$C->A[$i][$j] = $s;
 872								}
 873							}
 874							return $C;
 875						} else {
 876							throw new Exception(JAMAError(MatrixDimensionMismatch));
 877						}
 878						break;
 879				case 'array':
 880						$B = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 881						if ($this->n == $B->m) {
 882							$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n);
 883							for($i = 0; $i < $C->m; ++$i) {
 884								for($j = 0; $j < $C->n; ++$j) {
 885									$s = "0";
 886									for($k = 0; $k < $C->n; ++$k) {
 887										$s += $this->A[$i][$k] * $B->A[$k][$j];
 888									}
 889									$C->A[$i][$j] = $s;
 890								}
 891							}
 892							return $C;
 893						} else {
 894							throw new Exception(JAMAError(MatrixDimensionMismatch));
 895						}
 896						return $M;
 897						break;
 898				case 'integer':
 899						$C = new PHPExcel_Shared_JAMA_Matrix($this->A);
 900						for($i = 0; $i < $C->m; ++$i) {
 901							for($j = 0; $j < $C->n; ++$j) {
 902								$C->A[$i][$j] *= $args[0];
 903							}
 904						}
 905						return $C;
 906						break;
 907				case 'double':
 908						$C = new PHPExcel_Shared_JAMA_Matrix($this->m, $this->n);
 909						for($i = 0; $i < $C->m; ++$i) {
 910							for($j = 0; $j < $C->n; ++$j) {
 911								$C->A[$i][$j] = $args[0] * $this->A[$i][$j];
 912							}
 913						}
 914						return $C;
 915						break;
 916				case 'float':
 917						$C = new PHPExcel_Shared_JAMA_Matrix($this->A);
 918						for($i = 0; $i < $C->m; ++$i) {
 919							for($j = 0; $j < $C->n; ++$j) {
 920								$C->A[$i][$j] *= $args[0];
 921							}
 922						}
 923						return $C;
 924						break;
 925				default:
 926						throw new Exception(self::PolymorphicArgumentException);
 927						break;
 928			}
 929		} else {
 930			throw new Exception(self::PolymorphicArgumentException);
 931		}
 932	}	//	function times()
 933
 934
 935	/**
 936	 *	power
 937	 *
 938	 *	A = A ^ B
 939	 *	@param mixed $B Matrix/Array
 940	 *	@return Matrix Sum
 941	 */
 942	public function power() {
 943		if (func_num_args() > 0) {
 944			$args = func_get_args();
 945			$match = implode(",", array_map('gettype', $args));
 946
 947			switch($match) {
 948				case 'object':
 949						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
 950						break;
 951				case 'array':
 952						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
 953						break;
 954				default:
 955						throw new Exception(self::PolymorphicArgumentException);
 956						break;
 957			}
 958			$this->checkMatrixDimensions($M);
 959			for($i = 0; $i < $this->m; ++$i) {
 960				for($j = 0; $j < $this->n; ++$j) {
 961					$validValues = True;
 962					$value = $M->get($i, $j);
 963					if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) {
 964						$this->A[$i][$j] = trim($this->A[$i][$j],'"');
 965						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]);
 966					}
 967					if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) {
 968						$value = trim($value,'"');
 969						$validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value);
 970					}
 971					if ($validValues) {
 972						$this->A[$i][$j] = pow($this->A[$i][$j],$value);
 973					} else {
 974						$this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN();
 975					}
 976				}
 977			}
 978			return $this;
 979		} else {
 980			throw new Exception(self::PolymorphicArgumentException);
 981		}
 982	}	//	function power()
 983
 984
 985	/**
 986	 *	concat
 987	 *
 988	 *	A = A & B
 989	 *	@param mixed $B Matrix/Array
 990	 *	@return Matrix Sum
 991	 */
 992	public function concat() {
 993		if (func_num_args() > 0) {
 994			$args = func_get_args();
 995			$match = implode(",", array_map('gettype', $args));
 996
 997			switch($match) {
 998				case 'object':
 999						if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); }
1000				case 'array':
1001						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
1002						break;
1003				default:
1004						throw new Exception(self::PolymorphicArgumentException);
1005						break;
1006			}
1007			$this->checkMatrixDimensions($M);
1008			for($i = 0; $i < $this->m; ++$i) {
1009				for($j = 0; $j < $this->n; ++$j) {
1010					$this->A[$i][$j] = trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"');
1011				}
1012			}
1013			return $this;
1014		} else {
1015			throw new Exception(self::PolymorphicArgumentException);
1016		}
1017	}	//	function concat()
1018
1019
1020	/**
1021	 *	Solve A*X = B.
1022	 *
1023	 *	@param Matrix $B Right hand side
1024	 *	@return Matrix ... Solution if A is square, least squares solution otherwise
1025	 */
1026	public function solve($B) {
1027		if ($this->m == $this->n) {
1028			$LU = new PHPExcel_Shared_JAMA_LUDecomposition($this);
1029			return $LU->solve($B);
1030		} else {
1031			$QR = new QRDecomposition($this);
1032			return $QR->solve($B);
1033		}
1034	}	//	function solve()
1035
1036
1037	/**
1038	 *	Matrix inverse or pseudoinverse.
1039	 *
1040	 *	@return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise.
1041	 */
1042	public function inverse() {
1043		return $this->solve($this->identity($this->m, $this->m));
1044	}	//	function inverse()
1045
1046
1047	/**
1048	 *	det
1049	 *
1050	 *	Calculate determinant
1051	 *	@return float Determinant
1052	 */
1053	public function det() {
1054		$L = new PHPExcel_Shared_JAMA_LUDecomposition($this);
1055		return $L->det();
1056	}	//	function det()
1057
1058
1059}	//	class PHPExcel_Shared_JAMA_Matrix