Subversion Repositories eFlore/Applications.cel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2390 jpm 1
<?php
2
/**
3
 * @package JAMA
4
 */
5
 
6
/** PHPExcel root directory */
7
if (!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
 */
27
class 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 PHPExcel_Calculation_Exception(self::ArrayLengthException);
106
						}
107
						break;
108
				default:
109
						throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException);
110
						break;
111
			}
112
		} else {
113
			throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
181
						if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
194
						if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
207
						if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
220
						if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
233
						if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentBoundsException); }
246
						if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::PolymorphicArgumentException);
257
						break;
258
			}
259
		} else {
260
			throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::MatrixDimensionException);
278
			}
279
		} else {
280
			throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
432
						break;
433
				case 'array':
434
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
435
						break;
436
				default:
437
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
468
						break;
469
				case 'array':
470
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
471
						break;
472
				default:
473
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
518
						break;
519
				case 'array':
520
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
521
						break;
522
				default:
523
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
554
						break;
555
				case 'array':
556
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
557
						break;
558
				default:
559
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
605
						break;
606
				case 'array':
607
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
608
						break;
609
				default:
610
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
642
						break;
643
				case 'array':
644
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
645
						break;
646
				default:
647
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
693
						break;
694
				case 'array':
695
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
696
						break;
697
				default:
698
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
749
						break;
750
				case 'array':
751
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
752
						break;
753
				default:
754
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
786
						break;
787
				case 'array':
788
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
789
						break;
790
				default:
791
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
823
						break;
824
				case 'array':
825
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
826
						break;
827
				default:
828
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::PolymorphicArgumentException);
927
						break;
928
			}
929
		} else {
930
			throw new PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
950
						break;
951
				case 'array':
952
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
953
						break;
954
				default:
955
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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 PHPExcel_Calculation_Exception(self::ArgumentTypeException); }
1000
				case 'array':
1001
						$M = new PHPExcel_Shared_JAMA_Matrix($args[0]);
1002
						break;
1003
				default:
1004
						throw new PHPExcel_Calculation_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 PHPExcel_Calculation_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