1 /*!
  2 *
  3 *       JSMatrix : JavaScript matrix and vector implementation
  4 *                      version 0.5 (2011-09-19)
  5 *
  6 *                 Copyright (C)  2011  Jan Stransky
  7 *
  8 *      Czech Technical University, Faculty of Civil Engineering,
  9 *  Department of Structural Mechanics, 166 29 Prague, Czech Republic
 10 *
 11 *
 12 *  This program is free software: you can redistribute it and/or modify
 13 *  it under the terms of the GNU General Public License as published by
 14 *  the Free Software Foundation, either version 3 of the License, or
 15 *  (at your option) any later version.
 16 *
 17 *  This program is distributed in the hope that it will be useful,
 18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20 *  GNU General Public License for more details.
 21 *
 22 *  You should have received a copy of the GNU General Public License
 23 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 /**
 27 * @fileOverview JavaScript vector and matrix implementation. For more information see <a href="http://mech.fsv.cvut.cz/~stransky/software/jsmatrix/">project homepage</a>. The inspiration of publication "Press, W. H., Teukolsky, S. A., Vetterling, W. T. and Flannery, B. P. 2007. The Numerical Recipes: The Art of Scientific Computing, Third Edition" is gratefully acknowledged.
 28 <br /><br/>JSMatrix is a free software distributed under <a href='http://www.gnu.org/licenses/gpl.html'>GNU GPL license</a>.
 29 * @author <a href="http://mech.fsv.cvut.cz/~stransky/">Jan Stránský</a>
 30 * @version 0.5 (2011-09-19)
 31 */
 32 
 33 // constants for easier manipulation
 34 /**constant*/ var JSM_GAUSS       = 1;
 35 /**constant*/ var JSM_GAUSSJORDAN = 2;
 36 /**constant*/ var JSM_LU          = 3;
 37 /**constant*/ var JSM_LDU         = 4;
 38 /**constant*/ var JSM_CHOLESKY    = 5;
 39 /**constant*/ var JSM_QR          = 6;
 40 /**constant*/ var JSM_INV_IT      = 7;
 41 /**constant*/ var JSM_SUBSPACE    = 8;
 42 
 43 /**constant*/ var JSM_NOPIVOT   = 9;
 44 /**constant*/ var JSM_PARTPIVOT = 10;
 45 /**constant*/ var JSM_FULLPIVOT = 11;
 46 
 47 /**constant ( = 0 )*/ var X = 0;
 48 /**constant ( = 1 )*/ var Y = 1;
 49 /**constant ( = 2 )*/ var Z = 2;
 50 /**constant ( = 1e-8)*/ var JSM_TOL = 1e-8;
 51 
 52 /**@ignore*/ var JSM_DEBUG = 0;
 53 if (JSM_DEBUG) {
 54 	/**@ignore*/
 55 	assert = function(what,msg) {
 56 		if (!what) { alert("JSM_DEBUG:\n"+(msg||"")); }
 57 	}
 58 } else {
 59 	/**@ignore*/
 60 	assert = function() {}
 61 }
 62 
 63 
 64 
 65 
 66 
 67 /** Vector implementation
 68 * @class represents a vector (1D matrix) of real (floating point) numbers*/
 69 Vector = function() {
 70 	/** @property {int} [nItems=0] Number of items (elements) of receiver*/
 71 	this.nItems = 0;
 72 	/** @property {[floats]} [theArray=[]] array containing receiver's elements*/
 73 	this.theArray = [];
 74 }
 75 Vector.prototype = {
 76 	/**#@+
 77 	* @function
 78 	* @memberOf Vector#
 79 	*/
 80 
 81 	/** Zeros all elements of receiver
 82 	* @example v = vec([1,2,3,4]);
 83 	* v.zero(); // v = Vector([0,0,0,0])*/
 84 	zero: function() {
 85 		for (var r=0; r<this.nItems; r++) { this.theArray[r] = 0.; }
 86 	},
 87 	
 88 	/** Returns size (numer of elements) of receiver
 89 	* @returns {int} length (number of elements) of receiver
 90 	* @example v = vec([1,5,8,2]); var s = v.size(); // s = 4*/
 91 	size: function() {
 92 		return this.nItems;
 93 	},
 94 
 95 	/** Testing vector equality
 96 	* @param {Vector} vec vector to be compared with receiver
 97 	* @returns {bool} true if this==vec, false otherwise
 98 	* @example a = vec([1,2,3]);
 99 	* b = vec([1,2,2.999999999]);
100 	* c = vec([1,2,1]);
101 	* t1 = a.isEqualTo(b); // t1 = true
102 	* t2 = a.isEqualTo(c); // t2 = false*/
103 	isEqualTo: function(vec) {
104 		if (!this.isSameSizeAs(vec)) { return false; }
105 		var v = vec.theArray;
106 		for (var r=0; r<this.nItems; r++) {
107 			if (Math.abs(this.theArray[r]-v[r]) > JSM_TOL) { return false; }
108 		}
109 		return true;
110 	},
111 
112 	/** Returns one element of receiver ( ret = this[r] ) - numbering from 0
113 	* @param {int} r index of row (element) to be get (numbering from 0)
114 	* @returns {float} value of the r-th element
115 	* @example v = vec([4,7,2,4]); a = v.get(1); // a = 7*/
116 	get: function(r) {
117 		//assert(r < this.nItems,"Vector.get: r > this.nItems");
118 		return this.theArray[r];
119 	},
120 
121 	/** Set one element of receiver ( this[r] = val ) - numbering from 0
122 	* @param {int} r index of row (element) to be set (numbering from 0)
123 	* @param {float} val value to be set
124 	* @example v = vec([4,7,2,4]); v.set(1,68); // v = Vector([4,68,2,4])*/
125 	set: function(r,val) {
126 		this.theArray[r] = val;
127 	},
128 
129 	/** Increment one element of receiver ( this[r] += val ) - numbering from 0
130 	* @param {int} r index of row (element) to be incremented (numbering from 0)
131 	* @param {float} val value to be add
132 	* @example v = vec([4,7,2,4]); v.incr(1,4); // v = vec([4,11,2,4])*/
133 	incr: function(r,val) {
134 		if (val) { this.theArray[r] += val; }
135 	},
136 
137 	/*
138 	/* * Returns one element of receiver ( ret = this[r] ) - numbering from 1
139 	* @param {int} r index of row (element) to be get (numbering from 1)
140 	* @returns {float} value of the r-th element
141 	* @example v = vec([4,7,2,4]); a = v.get1(1); // a = 4* /
142 	get1: function(r) {
143 		return this.theArray[r-1];
144 	},
145 
146 	/* * Set one element of receiver ( this[r] = val ) - numbering from 1
147 	* @param {int} r index of row (element) to be set (numbering from 1)
148 	* @param {float} val value to be set
149 	* @example
150 	* v = vec([4,7,2,4]); v.set1(1,68); // v = vec([68,7,2,4])* /
151 	set1: function(r,val) {
152 		this.theArray[r-1] = val;
153 	},
154 
155 	/* * Increment one element of receiver ( this[r] += val ) - numbering from 1
156 	* @param {int} r index of row (element) to be incremented (numbering from 1)
157 	* @param {float} val value to be add
158 	* @example v = vec([4,7,2,4]); v.incr1(1,4); // v = vec([8,7,2,4])* /
159 	incr1: function(r,val) {
160 		if (val) { this.theArray[r-1] += val; }
161 	},
162 	*/
163 
164 	/** Testing vector's size equality
165 	* @param {Vector} vec vector to be tested
166 	* @returns {bool} true if vec and receiver has same size, false otherwise
167 	* @example a = vec([1,2,3,4]);
168 	* b = vec([5,6,7,8,9,10,11,12]);
169 	* c = vec([13,14,15,16]);
170 	* t1 = a.isSameSizeAs(b); // t1 = false
171 	* t2 = a.isSameSizeAs(c); // t1 = true*/
172 	isSameSizeAs: function(vec) {
173 		return (this.nItems==vec.nItems);
174 	},
175 	
176 	/** Testing if receiver can multiply given matrix ( this^T * mat )
177 	* @param {Matrix} mat matrix to be tested
178 	* @returns {bool} true if the multiplication is possible, false otherwise
179 	* @example v = vec([1,2,3]);
180 	* m1 = mat([[11,12,13],[21,22,23]]);
181 	* m2 = [[11,12],[21,22],[31,32]];
182 	* t1 = v.canMultiplyMat(m1); // t1 = true
183 	* t2 = v.canMultiplyMat(m2); // t2 = false*/
184 	canMultiplyMat: function(mat) {
185 		return this.nItems==mat.nCols;
186 	},
187 
188 	/** Sets elements of receiver form given array
189 	* @param {[floats]} arry array containing new receiver elements
190 	* @example v.fromArray([3,6,5,2]); // v = Vector([3,6,5,2])*/
191 	fromArray: function(arry) {
192 		this.nItems = arry.length;
193 		this.theArray = arry.slice();
194 	},
195 
196 	/** Returns elements of receiver as an array
197 	* @returns {[floats]} array containing receiver's elements
198 	* @example v =vec([3,4,5,6]); s = v.toArray(); // s = [3,4,5,6]*/
199 	toArray: function() {
200 		return this.theArray.slice();
201 	},
202 
203 	/** Returns sum of receiver and vector ( ret = this + vec )
204 	* @param {Vector} vec vector to be added
205 	* @returns {Vector} sum of receiver and vec
206 	* @example v1 = vec([1,2,3]);
207 	* v2 = vec([6,1,5]);
208 	* v3 = v1.add(v2); // v3 = Vector([7,3,8])*/
209 	add: function(vec) {
210 		if (!this.isSameSizeAs(vec)) { return null; }
211 		var v = vec.theArray;
212 		var ret = [];
213 		for (var r=0; r<this.nItems; r++) { ret[r] = this.theArray[r] + v[r]; }
214 		return Vector.create(ret);
215 	},
216 
217 	/** Add given vector to receiver ( this += vec )
218 	* @param {Vector} vec vector to be added
219 	* @example v1 = vec([1,2,3]);
220 	* v2 = vec([6,1,5]);
221 	* v1.iadd(v2); // v1 = Vector([7,3,8])*/
222 	iadd: function(vec) {
223 		if (!this.isSameSizeAs(vec)) { return null; }
224 		var v = vec.theArray;
225 		for (var r=0; r<this.nItems; r++) { this.theArray[r] += v[r]; }
226 	},
227 
228 	/** Returns difference of receiver and vector ( ret = this - vec )
229 	* @param {Vector} vec vector to be substracted
230 	* @returns {Vector} difference of receiver and vec
231 	* @example v1 = vec([1,2,3]);
232 	* v2 = vec([6,1,5]);
233 	* v3 = v1.sub(v2); // v3 = Vector([-5,1,-2])*/
234 	sub: function(vec) {
235 		if (!this.isSameSizeAs(vec)) { return null; }
236 		var v = vec.theArray;
237 		var ret = [];
238 		for (var r=0; r<this.nItems; r++) { ret[r] = this.theArray[r] - v[r]; }
239 		return Vector.create(ret);
240 	},
241 
242 	/** Substract given vector to receiver ( this -= vec )
243 	* @param {Vector} vec vector to be substracted
244 	* @example v1 = vec([1,2,3]);
245 	* v2 = vec([6,1,5]);
246 	* v1.isub(v2); // v1 = Vector([-5,1,-2])*/
247 	isub: function(vec) {
248 		if (!this.isSameSizeAs(vec)) { return null; }
249 		var v = vec.theArray;
250 		for (var r=0; r<this.nItems; r++) { this.theArray[r] -= v[r]; }
251 	},
252 
253 	/** Dot product of receiver and given vector
254 	* @param {Vector} vec vector for dot product
255 	* @param {int} [n=0] dot prodact will be made from first n elements. If not specified, zero or negative, all elements are used
256 	* @returns {float} dot product of receiver and vec from first n elements
257 	* @example v1 = vec([1,2,3]);
258 	* v2 = vec([6,1,5]);
259 	* d = v1.dot(v2,2); // d = 8*/
260 	dot: function(vec,n) {
261 		var n = n || 0;
262 		if (n<=0 || n>this.nItems) { n = this.nItems; }
263 		if (n > vec.nItems) { return null; }
264 		var v = vec.theArray;
265 		var ret = 0.;
266 		for (var r=0; r<n; r++) { ret += this.theArray[r]*v[r]; }
267 		return ret;
268 	},
269 
270 	/** Returns squared (Eucleidian) norm of receiver (ret = this.dot(this) )
271 	* @returns {float} squared Eucleidian norm of receiver
272 	* @example v = vec([4,2,4]);
273 	* n = v.squaredNorm(); // n = 36*/
274 	squaredNorm: function() {
275 		return this.dot(this);
276 	},
277 
278 	/** Returns (Eucleidian) norm of receiver (ret = sqrt(this.dot(this)) )
279 	* @returns {float} Eucleidian norm of receiver
280 	* @example v = vec([4,2,4]);
281 	* n = v.norm(); // n = 6*/
282 	norm: function() {
283 		return Math.sqrt(this.dot(this));
284 	},
285 
286 	/** Normlize receiver
287 	* @example v = vec([4,2,4]);
288 	* v.normalize(); // v = Vector([0.6666,0.5,0.66666])*/
289 	normalize: function() {
290 		var n = this.norm();
291 		this.imulf(1/n);
292 	},
293 
294 	/** Returns normalized copy of receiver
295 	* @returns {Vector} normalized copy of receiver
296 	* @example v1 = vec([4,2,4]);
297 	* v2 = v1.normalized(); // v2 = Vector([0.6666,0.5,0.66666])*/
298 	normalized: function() {
299 		var ret = this.copy();
300 		ret.normalize();
301 		return ret;
302 	},
303 
304 	/** Returns outer (dyadic, tensor, ...) product of receiver and given vector
305 	* @param {Vector} vec vector for multiplication
306 	* @returns {Matrix} outer product of receiver and vec
307 	* @example v1 = vec([1,2,3]);
308 	* v2 = vec([4,5,6]);
309 	* m = v1.outer(v2); // m = Matrix([[4,5,6],[8,10,12],[12,15,18]])*/
310 	outer: function(vec) {
311 		var ret = [];
312 		var v = vec.theArray;
313 		for (var r=0; r<this.nItems; r++) {
314 			ret[r] = [];
315 			for (var c=0; c<v.length; c++) { ret[r][c] = this.theArray[r] * v[c]; }
316 		}
317 		return Matrix.create(ret);
318 	},
319 
320 	/** Returns vector (cross) product of receiver and given vector. Both receiver and given vector have to be of length 3.
321 	* @param {Vector} vec vector for multiplication
322 	* @returns {Vector} cross product of receiver and vec
323 	* @example v1 = vec([1,2,3]);
324 	* v2 = vec([4,5,6]);
325 	* v3 = v1.cross(v2); // v = Vector([-3,6,-3])*/
326 	cross: function(vec) {
327 		if (this.nItems!=3 || vec.nItems!=3) { return null; }
328 		var v = vec.theArray;
329 		return Vector.create([
330 			this.theArray[Y]*v[Z]-this.theArray[Z]*v[Y],
331 			this.theArray[Z]*v[X]-this.theArray[X]*v[Z],
332 			this.theArray[X]*v[Y]-this.theArray[Y]*v[X]]);
333 	},
334 
335 	/** Returns negative of receiver ( ret = -this )
336 	* @returns {Vector} negative of receiver
337 	* @example v1 = vec([1,2,3]);
338 	* v2 = v1.negated(); // v2 = Vector([-1,-2,-3])*/
339 	negated: function() {
340 		var ret = this.copy();
341 		return ret.mulf(-1.);
342 	},
343 
344 	/** Alias for negated(), see {@link Vector#negated}*/
345 	neg: function() { return this.negated(); },
346 
347 	/** Negate receiver ( ret *= -1., ret = -ret )
348 	* @example v1 = vec([1,2,3]);
349 	* v1.negate(); // v1 = Vector([-1,-2,-3])*/
350 	negate: function() {
351 		for (var r=0; r<this.nItems; r++) { this.theArray[r] *= -1.; }
352 	},
353 
354 	/** Alias for neagete(), see {@link Vector#negate}*/
355 	ineg: function() { this.negate(); },
356 	
357 	/** Returns receiver multiplied by float f ( ret = this * f )
358 	* @param {float} f float multiplier
359 	* @returns {Vector} copy of receiver multiplied by f
360 	* @example v1 = vec([1,2,3]);
361 	* v2 = v1.mulf(3); // v2 = Vector([3,6,9])*/
362 	mulf: function(f) {
363 		var ret = [];
364 		for (var r=0; r<this.nItems; r++) { ret[r] = f*this.theArray[r]; }
365 		return Vector.create(ret);
366 	},
367 
368 	/** Multiply receiver by float f ( this *= f )
369 	* @param {float} f float multiplier
370 	* @example v = vec([1,2,3]);
371 	* v.imulf(3); // v = Vector([3,6,9])*/
372 	imulf: function(f) {
373 		for (var r=0; r<this.nItems; r++) { this.theArray[r] *= f; }
374 	},
375 
376 	/** Returns product of receiver and given matrix ( ret = this^T * mat )
377 	* @param {Matrix} mat matrix to multiply
378 	* @returns {Vector} copy of receiver multiplied by mat
379 	* @example v1 = vec([1,2,3]);
380 	* m = mat([[11,12,13],[21,22,23],[31,32,33]])
381 	* v2 = v1.mulm(m); // v2 = Vector([146,152,158])*/
382 	mulm: function(mat) {
383 		if (!this.canMultiplyMat(mat)) { return null; }
384 		var m = mat.theArray;
385 		var ret = [];
386 		var temp;
387 		for (var c=0; c<mat.nCols; c++) {
388 			temp = 0.;
389 			for (var r=0; r<this.nItems; r++) {
390 				temp += this.theArray[r]*m[r][c];
391 			}
392 			ret[c] = temp;
393 		}
394 		return Vector.create(ret);
395 	},
396 
397 	/** Returns product of receiver and given mltiplier (float or Matrix)
398 	* @param {Matrix|float} what matrix or float to multiply
399 	* @returns {Vector} copy of receiver multiplied by what
400 	* @example v1 = vec([1,2,3]);
401 	* v2 = v1.mul(mat([[11,12,13],[21,22,23],[31,32,33]])); // v2 = Vector([146,152,158])
402 	* v3 = v1.mul(3); // v3 = Vector([3,6,9])*/
403 	mul: function(what) {
404 		if (what instanceof Matrix) { return this.mulm(what); }
405 		if (typeof what == 'number') { return this.mulf(what); }
406 		return null;
407 	},
408 
409 	/** Alias for mul(), see {@link Vector#mul}*/
410 	x: function(what) { return this.mul(what); },
411 
412 	/** Returns subvector of receiver - numbering from 0
413 	* @param {[floats]|Vector} items array containing row indices of desired subvector - numbering from 0
414 	* @returns {Vector} desired subvector
415 	* @example v1 = vec([4,7,9,1,8,3,2,4,6,7,5,1,6,9]);
416 	* v2 = v1.getsv([2,3,6,8,9]); // v2 = Vector([9,1,2,6,7])*/
417 	getsv: function(items) {
418 		var items = items.theArray || items;
419 		var n = items.length;
420 		var ret = [];
421 		for (var r=0; r<n; r++) { ret[r] = this.theArray[items[r]]; }
422 		return Vector.create(ret);
423 	},
424 
425 	/** Set subvector to defined positions of receiver
426 	* @param {[floats]|Vector} items array containing row indices to be set - numbering from 0
427 	* @param {Vector|[floats]} vec vector to be set
428 	* @example v = vec([4,7,9,1,8,3,2,4,6,7,5,1,6,9]);
429 	* v.setsv([2,3,6,8,9],vec([1.1,2.2,3.3,4.4,5.5])); // v = Vector([4,7,1.1,2.2,8,3,3.3,4,4.4,5.5,5,1,6,9])*/
430 	setsv: function(items,vec) {
431 		var v = vec.theArray || vec;
432 		var items = items.theArray || items;
433 		var n = items.length;
434 		if (v.length != n) { return; }
435 		for (var r=0; r<n; r++) { this.theArray[items[r]] = v[r]; }
436 	},
437 
438 	/** Increment subvector to defined positions of receiver
439 	* @param {[floats]|Vector} items array containing row indices to be incremented - numbering from 0
440 	* @param {Vector|[floats]} vec vector to be added
441 	* @example v = vec([4,7,9,1,8,3,2,4,6,7,5,1,6,9]);
442 	* v.incrsv([2,3,6,8,9],vec([1.1,2.2,3.3,4.4,5.5])); // v = Vector([4,7,10.1,3.2,8,3,5.3,4,10.4,12.5,5,1,6,9])*/
443 	incrsv: function(items,vec) {
444 		var v = vec.theArray || vec;
445 		var items = items.theArray || items;
446 		var n = items.length;
447 		if (v.length != n) { return; }
448 		for (var r=0; r<n; r++) { this.theArray[items[r]] += v[r]; }
449 	},
450 
451 	/** Decrement subvector to defined positions of receiver
452 	* @param {[floats]|Vector} items array containing row indices to be decremented - numbering from 0
453 	* @param {Vector|[floats]} vec vector to be substracted
454 	* @example v = vec([4,7,9,1,8,3,2,4,6,7,5,1,6,9]);
455 	* v.decrsv([2,3,6,8,9],vec([1.1,2.2,3.3,4.4,5.5])); // v = Vector([4,7,7.9,-1.2,8,3,-1.3,4,1.6,1.5,5,1,6,9])*/
456 	decrsv: function(items,vec) {
457 		var v = vec.theArray || vec;
458 		var items = items.theArray || items;
459 		var n = items.length;
460 		if (v.length != n) { return; }
461 		for (var r=0; r<n; r++) { this.theArray[items[r]] -= v[r]; }
462 	},
463 
464 	/** Returns copy of receiver
465 	* @returns {Vector} copy of receiver
466 	* @example v1 = vec([1,2,3]);
467 	* v2 = v1;
468 	* v3 = v1.copy();
469 	* v1.set(1,6);
470 	* // v1; = Vector([1,6,3])
471 	* // v2; = Vector([1,6,3])
472 	* // v3; = Vector([1,2,3])*/
473 	copy: function() {
474 		var ret = new Vector();
475 		ret.fromArray(this.theArray.slice());
476 		return ret;
477 	},
478 
479 	/** Returns string representation of receiver
480 	* @returns {string} string representation of receiver
481 	* @example v1 = vec([1,2,3]);
482 	* alert(v1); // alerts "Vector([ 1, 2, 3 ])"*/
483 	toString: function() {
484 		var nn = this.nItems;
485 		if (nn == 0) { return "Vector([])\n"; }
486 		var ret = "Vector([ "
487 		for (var r=0; r<nn-1; r++) { ret += this.theArray[r]+", "; }
488 		ret += this.theArray[nn-1]+" ])\n";
489 		return ret;
490 	},
491 
492 	/** Swaps two items (items, elements..) of receiver - numbering from 0
493 	* @param {int} r1 index of first row to swap - numbering from 0
494 	* @param {int} r2 index of second row to swap - numbering from 0
495 	* @example v = vec([1,2,3,4,5,6,7]);
496 	* v.swapItems(1,4); // v = Vector([1,5,3,4,2,6,7])*/
497 	swapItems: function(r1,r2) {
498 		var row1 = this.theArray[r1];
499 		this.theArray[r1] = this.theArray[r2];
500 		this.theArray[r2] = row1;
501 	},
502 
503 	/** Appends given float/vector to the end of receiver
504 	* @param {float|Vector|[Vectors]} items new row(s) to be appended
505 	* @example v = vec([1,2]);
506 	* v.appendItems(4); // v = Vector([1,2,4]);
507 	* v.appendItems(vec([7,6])); // v = Vector([1,2,4,7,6]);
508 	* v.appendItems([vec([2,1]),vec([33,44])]); // v = Vector([1,2,4,7,6,2,1,33,44])*/
509 	appendItems: function(items) {
510 		if (items instanceof Vector) {
511 			for (var i=0; i<items.nItems; i++) {
512 				this.theArray[this.nItems] = items.theArray[i];
513 				this.nItems++;
514 			}
515 			return;
516 		}
517 		if (items instanceof Array) {
518 			for (var row=0; row<items.length; row++) {
519 				this.appendItems(items[row]);
520 			}
521 			return;
522 		}
523 		if (typeof items == 'number') {
524 			this.theArray[this.nItems] = items;
525 			this.nItems++;
526 			return;
527 		}
528 	},
529 
530 	/** Permute items of receiver according to given indices
531 	* @ param {[ints]|Vector} indx indices of permutation
532 	* @ param {bool} [backward=false] if false, receiver is permutated to given indices (forward). If true, from given indices (backward)
533 	* @ example v = vec([7,9,6]);
534 	* v.permuteItems([1,2,0]); // v = Vector([9,6,7])
535 	* v.permuteItems([1,2,0],true); // v = Vector([7,9,6])*/
536 	permuteItems: function(indx,backward) {
537 		var indx = indx.theArray || indx;
538 		if (indx.length != this.nItems) { return; }
539 		var backward = backward || false;
540 		var newArry = [];
541 		if (backward) {
542 			for (var i=0; i<this.nItems; i++) {
543 				newArry[i] = this.theArray[indx.indexOf(i)];
544 			}
545 			this.fromArray(newArry);
546 			return;
547 		}
548 		for (var i=0; i<this.nItems; i++) {
549 			newArry[i] = this.theArray[indx[i]];
550 		}
551 		this.fromArray(newArry);
552 	},
553 
554 	/** Returns permutated copy of receiver according to given indices
555 	* @ param {[ints]|Vector} indx indices of permutation
556 	* @ param {bool} [backward=false] if false, receiver is permutated to given indices (forward). If true, from given indices (backward)
557 	* @returns {Vector} permutated copy of receiver
558 	* @ example v1 = vec([7,9,6]);
559 	* v2 = v1.itemPermutation([1,2,0]); // v2 = Vector([9,6,7])
560 	* v3 = v1.itemPermutation([1,2,0],true); // v3 = Vector([6,7,9])*/
561 	itemPermutation: function(indx,backward) {
562 		var indx = indx.theArray || indx;
563 		if (indx.length != this.nItems) { return null; }
564 		var ret = this.copy();
565 		ret.permuteItems(indx,backward);
566 		return ret;
567 	},
568 
569 	/** Resize receiver according to given size (delete extra elements or add zero elements)
570 	* @param {int} nItems new number of items
571 	* @example v1 = vec([4,7,9,1,7,3])
572 	* v2 = vec([4,6]);
573 	* v1.resize(4); // v1 = Vector([4,7,9,1])
574 	* v2.resize(4); // v2 = Vector([4,6,0,0])*/
575 	resize: function(nItems) {
576 		if (nItems==this.nItems) { return; }
577 		if (nItems > this.nItems) {
578 			for (var r=this.nItems; r<nItems; r++) { this.theArray[r] = 0.; }
579 			this.nItems = nItems;
580 			return;
581 		}
582 		if (nItems < this.nItems) {
583 			this.theArray = this.theArray.slice(0,nItems);
584 			this.nItems = nItems;
585 		}
586 	},
587 	/** Returns resized copy of receiver according to given size (delete extra elements or add zero elements)
588 	* @param {int} nItems new number of items
589 	* @returns {Vector} resized copy of receiver
590 	* @example v1 = vec([4,7,9,1]);
591 	* v2 = v1.resized(2); // v2 = Vector([4,7])
592 	* v3 = v1.resized(6); // v3 = Vector([4,7,9,1,0,0])*/
593 	resized: function(nItems) {
594 		var ret = this.copy();
595 		ret.resize(nItems);
596 		return ret;
597 	},
598 
599 	/** Returns matrix with receiver's elements on its diagonal
600 	* @returns {Matrix} diagonal matrix with receiver's elements on its diagonal
601 	* @example v = vec([1,2,3]);
602 	* m = v.toDiagonalMatrix(); // m = Matrix([[1,0,0],[0,2,0],[0,0,3]])*/
603 	toDiagonalMatrix: function() {
604 		var ret = Matrix.Zeros(this.nItems,this.nItems);
605 		for (var r=0; r<this.nItems; r++) { ret.theArray[r][r] = this.theArray[r]; }
606 		return ret;
607 	},
608 
609 	/** Alias for toDiagonalMatrix(), see {@link Vector#toDiagonalMatrix}*/
610 	diag: function() { return this.toDiagonalMatrix(); },
611 
612 	/**#@-*/
613 }
614 
615 /** Constructs new Vector from given array
616 * @param {[floats]} [arry=[]] array containing elements of new vector
617 * @returns {Vector} new Vector object 
618 * @example v = Vector.create([1,2,3,4]) // v = Vector([1,2,3,4])*/
619 Vector.create = function(arry) {
620 	var a = (arry==null)? []:arry.slice();
621 	var ret = new Vector();
622 	ret.fromArray(a);
623 	return ret;
624 }
625 
626 /** Creates unit vector in x direction
627 * @returns {Vector} unit x vector
628 * @example v = UnitX // v = Vector([1,0,0])*/
629 Vector.UnitX = Vector.create([1,0,0]);
630 
631 /** Creates unit vector in y direction
632 * @returns {Vector} unit y vector
633 * @example v = UnitX // v = Vector([0,1,0])*/
634 Vector.UnitY = Vector.create([0,1,0]);
635 
636 /** Creates unit vector in z direction
637 * @returns {Vector} unit z vector
638 * @example v = UnitX // v = Vector([0,0,1])*/
639 Vector.UnitZ = Vector.create([0,0,1]);
640 
641 /** Creates a vector full of zeros
642 * @param {int} [nItems=0] number of elements
643 * @returns {Vector} new vector full of zeros
644 * @example v = Vector.Zeros(4) // v = Vector([0,0,0,0])*/
645 Vector.Zeros = function(nItems) {
646 	var nItems = nItems || 0;
647 	var arry = [];
648 	for (var i=0; i<nItems; i++) { arry.push(0.); }
649 	return Vector.create(arry);
650 }
651 
652 /** Creates a vector full of ones
653 * @param {int} [nItems=0] number of elements
654 * @returns {Vector} new vector full of zeros
655 * @example v = Vector.Ones(6) // v = Vector([1,1,1,1,1,1])*/
656 Vector.Ones = function(nItems) {
657 	var nItems = nItems || 0;
658 	var arry = [];
659 	for (var i=0; i<nItems; i++) { arry.push(1.); }
660 	return Vector.create(arry);
661 }
662 
663 
664 
665 
666 
667 /** Matrix implementation
668 * @class represents a 2D matrix of real (floating point) numbers
669 * @property {int} [nRows=0] Number of rows of receiver
670 * @property {int} [nCols=0] Number of columns of receiver
671 * @property {[floats]} [theArray=[]] Array (2D) containing receiver's elements*/
672 Matrix = function(nRows,nCols) {
673 	this.nRows = nRows || 1;
674 	this.nCols = nCols || 0;
675 	this.theArray = [[]];
676 }
677 Matrix.prototype = {
678 	/**#@+
679 	* @function
680 	* @memberOf Matrix#
681 	*/
682 
683 	/** Zeros all elements of receiver
684 	* @example m = mat([[1,2,3],[4,5,6],[7,8,9]]);
685 	* m.zero(); // m = Matrix([[0,0,0],[0,0,0],[0,0,0]])*/
686 	zero: function() {
687 		for (var r=0; r<this.nRows; r++) {
688 			this.theArray[r] = []
689 			for (var c=0; c<this.nCols; c++) { this.theArray[r][c] = 0.; }
690 		}
691 	},
692 
693 	/** Returns size of receiver as [nRows,nCols]
694 	* @returns {[int,int]} array as [number of rows,number of columns]
695 	* @example m = mat([[1,2,3],[4,5,6]]);
696 	* s = m.size(); // s = [2,3]*/
697 	size: function() {
698 		return [this.nRows,this.nCols];
699 	},
700 
701 	/** Testing matrix equality
702 	* @param {Matrix} mat matrix to be compared with receiver
703 	* @returns {bool} true if this==mat, false otherwise
704 	* @example a = mat([[1,2,3],[4,5,6],[7,8,9]]);
705 	* b = mat([[1,2,2.999999999],[4.0000000000002,5,6],[7,8,8.9999999999]]);
706 	* c = mat([[1,2,3],[4,5,6],[7,8,9],[10,11,12]]);
707 	* t1 = a.isEqualTo(b); // t1 = true
708 	* t2 = a.isEqualTo(c); // t2 = false*/
709 	isEqualTo: function(mat) {
710 		if (!this.isSameSizeAs(mat)) { return false; }
711 		var m = mat.theArray;
712 		for (var r=0; r<this.nRows; r++) {
713 			for (var c=0; c<this.nCols; c++) {
714 				if (Math.abs(this.theArray[r][c] - m[r][c]) > JSM_TOL) { return false; }
715 			}
716 		}
717 		return true;
718 	},
719 
720 	/** Returns one element of receiver ( ret = this[r,c] ) - numbering from 0
721 	* @param {int} r index of row to be get (numbering from 0)
722 	* @param {int} c index of column to be get (numbering from 0)
723 	* @returns {float} value of the element at r-th row and c-th column
724 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
725 	* g = m.get(1,2); // g = 23*/
726 	get: function(r,c) {
727 		return this.theArray[r][c];
728 	},
729 
730 	/** Set one element of receiver ( this[r,c] = val ) - numbering from 0
731 	* @param {int} r index of row to be set (numbering from 0)
732 	* @param {int} c index of column to be set (numbering from 0)
733 	* @param {float} val value to be set
734 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
735 	* m.set(1,2,3.45); // m = Matrix([[11,12,13],[21,22,3.45],[31,32,33]])
736 	*/
737 	set: function(r,c,val) {
738 		this.theArray[r][c] = val;
739 	},
740 
741 	/** Increment one element of receiver ( this[r,c] += val ) - numbering from 0
742 	* @param {int} r index of row to be incremented (numbering from 0)
743 	* @param {int} c index of column to be incremented (numbering from 0)
744 	* @param {float} val value to be add
745 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
746 	* m.incr(1,2,3.45); // m = Matrix([[11,12,13],[21,22,26.45],[31,32,33]])
747 	*/
748 	incr: function(r,c,val) {
749 		if (val) { this.theArray[r][c] += val; }
750 	},
751 
752 	/** Testing matrix size equality
753 	* @param {Matrix} mat matrix to be tested
754 	* @returns {bool} true if mat and receiver has same size, false otherwise
755 	* @example a = mat([[1,2,3],[4,5,6]]);
756 	* b = mat([[5,6,7],[8,9,10],[11,12,13]]);
757 	* c = mat([[14,15,16],[17,18,19]]);
758 	* t1 = a.isSameSizeAs(b); // t1 = false
759 	* t2 = a.isSameSizeAs(c); // t1 = true*/
760 	isSameSizeAs: function(mat) {
761 		return (this.nRows==mat.nRows && this.nCols==mat.nCols);
762 	},
763 
764 	/** Testing if receiver can multiply given matrix ( this * mat )
765 	* @param {Matrix} mat matrix to be tested
766 	* @returns {bool} true if the multiplication is possible, false otherwise
767 	* @example m1 = mat([[1,2,3],[4,5,6]]);
768 	* m2 = mat([[7,8,9],[10,11,12]]);
769 	* m3 = mat([[11,12],[21,22],[31,32]]);
770 	* t1 = m1.canMultiplyMat(m2); // t1 = false
771 	* t2 = m1.canMultiplyMat(m3); // t2 = true*/
772 	canMultiplyMat: function(mat) {
773 		return (this.nCols==mat.nRows);
774 	},
775 
776 	/** Testing if receiver can multiply given vector ( this * vec )
777 	* @param {Vector} vec vector to be tested
778 	* @returns {bool} true if the multiplication is possible, false otherwise
779 	* @example m = mat([[1,2,3],[4,5,6]]);
780 	* v1 = vec([1,2,3]);
781 	* v2 = vec([4,5]);
782 	* t1 = m.canMultiplyVec(v1); // t1 = true
783 	* t2 = m.canMultiplyVec(v2); // t2 = false*/
784 	canMultiplyVec: function(vec) {
785 		return (this.nCols==vec.nItems);
786 	},
787 
788 	/** Testing if receiver is square
789 	* @returns {bool} true if receiver is square matrix, false otherwise
790 	* @example m1 = mat([[1,2,3],[4,5,6]]);
791 	* m2 = mat([[1,2,3],[4,5,6],[7,8,9]]);
792 	* t1 = m1.isSquare(); // t1 = false
793 	* t2 = m2.isSquare(); // t2 = true*/
794 	isSquare: function() {
795 		return (this.nRows==this.nCols);
796 	},
797 
798 	/** Testing if receiver is symmetric matrix
799 	* @returns {bool} true if receiver is symmetric, false otherwise
800 	* @example m1 = mat([[11,12,13],[21,22,23],[31,32,33]]);
801 	* m2 = mat([[11,12,13],[12,22,23],[13,23,33]]);
802 	* t1 = m1.isSymmetric(); // t1 = false
803 	* t2 = m2.isSymmetric(); // t2 = true*/
804 	isSymmetric: function() {
805 		if (!this.isSquare()) { return false; }
806 		for (var r=0; r<this.nRows; r++) {
807 			for (var c=r+1; c<this.nCols; c++) {
808 				if (Math.abs(this.theArray[r][c] - this.theArray[c][r]) > JSM_TOL) { return false; }
809 			}
810 		}
811 		return true;
812 	},
813 
814 	/** Testing if receiver is lower triangular matrix
815 	* @returns {bool} true if receiver is lower triangular, false otherwise
816 	* @example m1 = mat([[1,2,3],[4,5,6],[7,8,9]]);
817 	* m2 = mat([[1,0,0],[4,5,0],[7,8,9]]);
818 	* t1 = m1.isLowerTriangular(); // t1 = false
819 	* t2 = m2.isLowerTriangular(); // t2 = true*/
820 	isLowerTriangular: function() {
821 		for (var r=0; r<this.nRows; r++) {
822 			for (var c=r+1; c<this.nCols; c++) {
823 				if (Math.abs(this.theArray[r][c]) > JSM_TOL) { return false; }
824 			}
825 		}
826 		return true;
827 	},
828 
829 	/** Testing if receiver is upper triangular matrix
830 	* @returns {bool} true if receiver is upper triangular, false otherwise
831 	* @example m1 = mat([[1,2,3],[4,5,6],[7,8,9]]);
832 	* m2 = mat([[1,2,3],[0,5,6],[0,0,9]]);
833 	* t1 = m1.isUpperTriangular(); // t1 = false
834 	* t2 = m2.isUpperTriangular(); // t2 = true*/
835 	isUpperTriangular: function() {
836 		for (var r=0; r<this.nRows; r++) {
837 			for (var c=0; c<r; c++) {
838 				if (Math.abs(this.theArray[r][c]) > JSM_TOL) { return false; }
839 			}
840 		}
841 		return true;
842 	},
843 
844 	/** Sets elements of receiver form given array
845 	* @param {[floats](2D)} arry array containing new receiver elements
846 	* @example m.fromArray([[1,2,3],[4,5,6],[7,8,9]]); // m = Matrix([[1,2,3],[4,5,6],[7,8,9]])*/
847 	fromArray: function(arry) {
848 		this.nRows = arry.length;
849 		if (this.nRows) { this.nCols = arry[0].length; }
850 		else { this.nCols = 0; }
851 		this.theArray = []
852 		for (var r=0; r<this.nRows; r++) {
853 			this.theArray[r] = arry[r].slice();
854 		}
855 	},
856 
857 	/** Returns elements of receiver as an array
858 	* @returns {[floats](2D)} array containing receiver's elements
859 	* @example m =mat([[11,12],[21,22]]);
860 	* a = m.toArray(); // a = [[11,12],[21,22]]*/
861 	toArray: function() {
862 		var ret = []
863 		for (var r=0; r<this.nRows; r++) { ret[r] = this.theArray[r].slice(); }
864 		return ret;
865 	},
866 
867 	/** Returns sum of receiver and matrix ( ret = this + mat )
868 	* @param {Matrix} mat vector to be added
869 	* @returns {Matrix} sum of receiver and matrix
870 	* @example m1 = mat([[1,2],[3,4]]);
871 	* m2 = mat([[2,5],[3,2]]);
872 	* m3 = m1.add(m2); // m3 = Matrix([[3,7],[6,6]])*/
873 	add: function(mat) {
874 		if (!this.isSameSizeAs(mat)) { return null; }
875 		var m = mat.theArray;
876 		var ret = [];
877 		for (var r=0; r<this.nRows; r++) {
878 			ret[r] = [];
879 			for (var c=0; c<this.nCols; c++) { ret[r][c] = this.theArray[r][c] + m[r][c]; }
880 		}
881 		return Matrix.create(ret);
882 	},
883 
884 	/** Add given matrix to receiver ( this += mat )
885 	* @param {Matrix} mat vector to be added
886 	* @example m1 = mat([[1,2],[3,4]]);
887 	* m2 = mat([[2,5],[3,2]]);
888 	* m1.iadd(m2); // m1 = Matrix([[3,7],[6,6]])*/
889 	iadd: function(mat) {
890 		if (!this.isSameSizeAs(mat)) { return null; }
891 		var m = mat.theArray;
892 		for (var r=0; r<this.nRows; r++) {
893 			for (var c=0; c<this.nCols; c++) { this.theArray[r][c] += m[r][c]; }
894 		}
895 	},
896 
897 	/** Returns difference of receiver and matrix ( ret = this - mat )
898 	* @param {Matrix} mat vector to be added
899 	* @returns {Matrix} sum of receiver and matrix
900 	* @example m1 = mat([[1,2],[3,4]]);
901 	* m2 = mat([[2,5],[3,2]]);
902 	* m3 = m1.sub(m2); // m3 = Matrix([[-1,-3],[0,2]])*/
903 	sub: function(mat) {
904 		if (!this.isSameSizeAs(mat)) { return null; }
905 		var m = mat.theArray;
906 		var ret = [];
907 		for (var r=0; r<this.nRows; r++) {
908 			ret[r] = [];
909 			for (var c=0; c<this.nCols; c++) { ret[r][c] = this.theArray[r][c] - m[r][c]; }
910 		}
911 		return Matrix.create(ret);
912 	},
913 
914 	/** Substract given matrix to receiver ( this -= mat )
915 	* @param {Matrix} mat vector to be added
916 	* @example m1 = mat([[1,2],[3,4]]);
917 	* m2 = mat([[2,5],[3,2]]);
918 	* m1.isub(m2); // m1 = Matrix([[-1,-3],[0,2]])*/
919 	isub: function(mat) {
920 		if (!this.isSameSizeAs(mat)) { return null; }
921 		var m = mat.theArray;
922 		for (var r=0; r<this.nRows; r++) {
923 			for (var c=0; c<this.nCols; c++) { this.theArray[r][c] -= m[r][c]; }
924 		}
925 	},
926 
927 	/** Returns negative of receiver ( ret = -this )
928 	* @returns {Matrix} negative of receiver
929 	* @example m1 = mat([[1,2,3],[4,5,6]]);
930 	* m2 = m1.negated(); // m2 = Matrix([[-1,-2,-3],[-4,-5,-6]])*/
931 	negated: function() {
932 		var ret = this.copy()
933 		return ret.mulf(-1.);
934 	},
935 
936 	/** Alias for neageted(), see {@link Matrix#negated}*/
937 	neg: function() { return this.negated(); },
938 
939 	/** Negate receiver ( ret *= -1., ret = -ret )
940 	* @example m1 = mat([[1,2,3],[4,5,6]]);
941 	* m1.negate(); // m1 = Matrix([[-1,-2,-3],[-4,-5,-6]])*/
942 	negate: function() {
943 		for (var r=0; r<this.nRows; r++) {
944 			for (var c=0; c<this.nCols; c++) { this.theArray[r][c] *= -1.; }
945 		}
946 	},
947 
948 	/** Alias for neagete(), see {@link Matrix#negate}*/
949 	ineg: function() { this.negate(); },
950 
951 	/** Returns one row of receiver - numbering from 0
952 	* @param {int} r index of row to return - numbering from 0
953 	* @returns {Vector} r-th row of receiver as vector
954 	* @example m = m([[1,2,3],[4,5,6],[7,8,9]]);
955 	* v = mat.getRow(1); // v = Vector([4,5,6])*/
956 	getRow: function(r) {
957 		return Vector.create(this.theArray[r].slice())
958 	},
959 
960 	/** Returns one column of receiver - numbering from 0
961 	* @param {int} c index of column to return - numbering from 0
962 	* @returns {Vector} c-th column of receiver as vector
963 	* @example m = m([[1,2,3],[4,5,6],[7,8,9]]);
964 	* v = mat.getCol(1); // v = Vector([2,5,8])*/
965 	getCol: function(c) {
966 		var ret = []
967 		for (var r=0; r<this.nRows; r++) { ret[r] = this.theArray[r][c]; }
968 		return Vector.create(ret);
969 	},
970 
971 	/** Sets one row of receiver - numbering from 0
972 	* @param {int} r index of row to set - numbering from 0
973 	* @param {Vector} vec vector to be set as new r-th row
974 	* @example mat([[1,2,3],[4,5,6],[7,8,9]]);
975 	* m.setRow(1,vec([11,12,13])); // m = Matrix([[1,2,3],[11,12,13],[7,8,9]])*/
976 	setRow: function(r,vec) {
977 		if (this.nCols != vec.nItems) { return; }
978 		var v = vec.theArray;
979 		this.theArray[r] = v.slice();
980 	},
981 
982 	/** Sets one column of receiver - numbering from 0
983 	* @param {int} c index of column to set - numbering from 0
984 	* @param {Vector} vec vector to be set as new r-th row
985 	* @example m = mat([[1,2,3],[4,5,6],[7,8,9]]);
986 	* m.setCol(1,vec([11,12,13])); // m = Matrix([[1,11,3],[4,12,6],[7,13,9]])*/
987 	setCol: function(c,vec) {
988 		if (this.nRows != vec.nItems) { return; }
989 		var v = vec.theArray;
990 		for (var r=0; r<this.nRows; r++) {
991 			this.theArray[r][c] = v[r];
992 		}
993 	},
994 
995 	/** Swaps two rows of receiver - numbering from 0
996 	* @param {int} r1 index of first row to swap - numbering from 0
997 	* @param {int} r2 index of second row to swap - numbering from 0
998 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
999 	* m.swapRows(0,2); // m = Matrix([[31,32,33],[21,22,23],[11,12,13]])*/
1000 	swapRows: function(r1,r2) {
1001 		var row1 = this.theArray[r1];
1002 		this.theArray[r1] = this.theArray[r2];
1003 		this.theArray[r2] = row1;
1004 	},
1005 
1006 	/** Swaps two columns of receiver - numbering from 0
1007 	* @param {int} c1 index of first row to swap - numbering from 0
1008 	* @param {int} c2 index of second row to swap - numbering from 0
1009 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
1010 	* m.swapCols(0,2); // m = Matrix([[13,12,11],[23,22,21],[33,32,31]])*/
1011 	swapCols: function(c1,c2) {
1012 		var temp
1013 		for (var r=0; r<this.nRows; r++) {
1014 			temp = this.theArray[r][c1];
1015 			this.theArray[r][c1] = this.theArray[r][c2];
1016 			this.theArray[r][c2] = temp;
1017 		}
1018 	},
1019 
1020 	/** Permute rows of receiver according to given indices
1021 	* @ param {[ints]|Vector} indx indices of row permutation
1022 	* @ param {bool} [backward=false] if false, receiver's rows is permutated to given indices (forward). If true, from given indices (backward)
1023 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
1024 	* m.permuteRows([1,2,0]); // m = Matrix([[21,22,23],[31,32,33],[11,12,13]])
1025 	* m.permuteRows([1,2,0],true); // m = mat([[11,12,13],[21,22,23],[31,32,33]])*/
1026 	permuteRows: function(indx,backward) {
1027 		var indx = indx.theArray || indx;
1028 		if (indx.length != this.nRows) { return null; }
1029 		var backward = backward || false;
1030 		var newArry = [];
1031 		if (backward) {
1032 			for (var i=0; i<this.nRows; i++) {
1033 				newArry[i] = this.theArray[indx.indexOf(i)].slice();
1034 			}
1035 			this.fromArray(newArry);
1036 			return;
1037 		}
1038 		for (var i=0; i<this.nRows; i++) {
1039 			newArry[i] = this.theArray[indx[i]].slice();
1040 		}
1041 		this.fromArray(newArry);
1042 	},
1043 
1044 	/** Returns copy of receiver with rows permutated according to given indices
1045 	* @ param {[ints]|Vector} indx indices of permutation
1046 	* @ param {bool} [backward=false] if false, receiver is permutated to given indices (forward). If true, from given indices (backward)
1047 	* @returns {Matrix} copy of receiver with permutated rows
1048 	* @example m1 = mat([[11,12,13],[21,22,23],[31,32,33]]);
1049 	* m2 = m1.permuteRows([1,2,0]); // m2 = Matrix([[21,22,23],[31,32,33],[11,12,13]])
1050 	* m3 = m1.permuteRows([1,2,0],true); // m3 = mat([[31,32,33],[11,12,13],[21,22,23]])*/
1051 	rowPermutation: function(indx,backward) {
1052 		var indx = indx.theArray || indx;
1053 		var backward = backward || false;
1054 		if (indx.length != this.nRows) { return null; }
1055 		var ret = this.copy();
1056 		ret.permuteRows(indx,backward);
1057 		return ret;
1058 	},
1059 
1060 	/** Returns receiver multiplied by float f ( ret = this * f )
1061 	* @param {float} f float multiplier
1062 	* @returns {Matrix} copy of receiver multiplied by f
1063 	* @example m1 = mat([[1,2,3],[4,5,6]]);
1064 	* m2 = m1.mulf(3); // m2 = Matrix([[3,6,9],[12,15,18]])*/
1065 	mulf: function(f) {
1066 		var ret = this.copy()
1067 		ret.imulf(f)
1068 		return ret;
1069 	},
1070 
1071 	/** Multiply receiver by float f ( this *= f )
1072 	* @param {float} f float multiplier
1073 	* @example m = mat([[1,2,3],[4,5,6]]);
1074 	* m.imulf(3); // m = Matrix([[3,6,9],[12,15,18]])*/
1075 	imulf: function(f) {
1076 		for (var r=0; r<this.nRows; r++) {
1077 			for (var c=0; c<this.nCols; c++) { this.theArray[r][c] *= f; }
1078 		}
1079 	},
1080 
1081 	/** Returns product of receiver and given vector ( ret = this * vec )
1082 	* @param {Vector} vec vector to multiply
1083 	* @returns {Vector} copy of receiver multiplied by vec
1084 	* @example m = mat([[11,12,13],[21,22,23],[31,32,33]]);
1085 	* v1 = vec([1,2,3]);
1086 	* v2 = m.mulv(v1); // v2 = Vector([74,134,194])*/
1087 	mulv: function(vec) {
1088 		if (!this.canMultiplyVec(vec)) { return null; }
1089 		var v = vec.theArray;
1090 		var ret = [];
1091 		var temp;
1092 		for (var r=0; r<this.nRows; r++) {
1093 			temp = 0.
1094 			for (var c=0; c<this.nCols; c++) {
1095 				temp += this.theArray[r][c]*v[c]
1096 			}
1097 			ret[r] = temp;
1098 		}
1099 		return Vector.create(ret);
1100 	},
1101 
1102 	/** Returns product of receiver and given matrix ( ret = this * mat )
1103 	* @param {Matrix} mat matrix to multiply
1104 	* @returns {Matrix} copy of receiver multiplied by mat
1105 	* @example m1 = mat([[11,12],[21,22]]);
1106 	* m2 = mat([[1,2],[3,4]]);
1107 	* m3 = m1.mulm(m2); // m3 = Matrix([[47,70],[87,130]])*/
1108 	mulm: function(mat) {
1109 		if (!this.canMultiplyMat(mat)) { return null; }
1110 		var m = mat.theArray;
1111 		var ret = [];
1112 		var temp;
1113 		for (var r=0; r<this.nRows; r++) {
1114 			ret[r] = [];
1115 			for (var c=0; c<mat.nCols; c++) {
1116 				temp = 0.;
1117 				for (var k=0; k<this.nCols; k++) {
1118 					temp += this.theArray[r][k]*m[k][c]
1119 				}
1120 				ret[r][c] = temp;
1121 			}
1122 		}
1123 		return Matrix.create(ret);
1124 	},
1125 
1126 	/** Returns product of receiver and given mltiplier (float or Matrix)
1127 	* @param {Matrix|Vector|float} what matrix or vector or float to multiply
1128 	* @returns {Matrix|Vector} copy of receiver multiplied by what
1129 	* @example m1 = mat([[1,2,3],[4,5,6]]);
1130 	* m2 = m1.mulf(3); // m2 = Matrix([[3,6,9],[12,15,18]])
1131 	*
1132 	* m3 = mat([[11,12,13],[21,22,23],[31,32,33]]);
1133 	* v1 = vec([1,2,3]);
1134 	* v2 = m3.mulv(v1) // v2 = Vector([74,134,194]);
1135 	*
1136 	* m4 = mat([[11,12],[21,22]]);
1137 	* m5 = mat([[1,2],[3,4]]);
1138 	* m6 = m4.mulm(m5); // m6 = Matrix([[47,70],[87,130]])*/
1139 	mul: function(what) {
1140 		if (what instanceof Vector) { return this.mulv(what); }
1141 		if (what instanceof Matrix) { return this.mulm(what); }
1142 		if (typeof what == 'number') { return this.mulf(what); }
1143 		return null;
1144 	},
1145 
1146 	/** Alias for mul(), see {@link Matrix#mul}*/
1147 	x: function(what) { return this.mul(what); },
1148 
1149 	/** Returns transposition of receiver ( ret = this^T )
1150 	* @returns {Matrix} transposed copy of receiver
1151 	* @example m1 = mat([[1,2,3],[4,5,6]]);
1152 	* m2 = m1.transposed(); // m2 = Matrix([[1,4],[2,5],[3,6]])*/
1153 	transposed: function() {
1154 		var ret = [];
1155 		for (var r=0; r<this.nCols; r++) {
1156 			ret[r] = [];
1157 			for (var c=0; c<this.nRows; c++) {
1158 				ret[r][c] = this.theArray[c][r];
1159 			}
1160 		}
1161 		return Matrix.create(ret);
1162 	},
1163 
1164 	/** Alias for transposed(), see {@link Matrix#transposed}*/
1165 	T: function() { return this.transposed(); },
1166 
1167 	/** Returns submatrix of receiver - numbering from 0
1168 	* @param {[floats]|Vector} rows array containing rowa indices of desired submatrix - numbering from 0
1169 	* @param {[floats]|Vector} cols array containing columns indices of desired submatrix - numbering from 0
1170 	* @returns {Matrix} desired submatrix
1171 	* @example m1 = mat([[11,12,13,14],[21,22,23,24],[31,32,33,34],[41,42,43,44]]);
1172 	* m2 = m1.getsm([1,2],[0,2]); // m2 = Matrix([[21,23],[31,33]])*/
1173 	getsm: function(rows,cols) {
1174 		var nr = rows.nItems || rows.length
1175 		var nc = cols.nItems || cols.length
1176 		var rows = rows.theArray || rows;
1177 		var cols = cols.theArray || cols;
1178 		var ret = [];
1179 		for (var r=0; r<nr; r++) {
1180 			ret[r] = [];
1181 			for (var c=0; c<nc; c++) { ret[r][c] = this.theArray[rows[r]][cols[c]]; }
1182 		}
1183 		return Matrix.create(ret);
1184 	},
1185 
1186 	/** Set submatrix to defined positions of receiver
1187 	* @param {[floats]|Vector} rows array containing rows indices to be set - numbering from 0
1188 	* @param {[floats]|Vector} cols array containing columns indices to be set - numbering from 0
1189 	* @param {Matrix} mat matrix to be set on desired positions
1190 	* @example m = mat([[11,12,13,14],[21,22,23,24],[31,32,33,34],[41,42,43,44]]);
1191 	* m.setsm([1,2],[0,2],mat([[66,77],[88,99]]));
1192 	* // m = Matrix([[11,12,13,14],[66,22,77,24],[88,32,99,34],[41,42,43,44]])*/
1193 	setsm: function(rows,cols,mat) {
1194 		var rows = rows.theArray || rows;
1195 		var cols = cols.theArray || cols;
1196 		var nr = rows.length;
1197 		var nc = cols.length;
1198 		if (mat.nRows != nr || mat.nCols != nc) { return; }
1199 		var m = mat.theArray;
1200 		for (var r=0; r<nr; r++) {
1201 			for (var c=0; c<nc; c++) { this.theArray[rows[r]][cols[c]] = m[r][c]; }
1202 		}
1203 	},
1204 
1205 	/** Increment submatrix at defined positions of receiver
1206 	* @param {[floats]|Vector} rows array containing rows indices to be incrementes - numbering from 0
1207 	* @param {[floats]|Vector} cols array containing columns indices to be incremented - numbering from 0
1208 	* @param {Matrix} mat matrix to be incremented on desired positions
1209 	* @example m = mat([[11,12,13,14],[21,22,23,24],[31,32,33,34],[41,42,43,44]]);
1210 	* m.incrsm([1,2],[0,2],mat([[66,77],[88,99]]));
1211 	* // m = Matrix([11,12,13,14],[87,22,110,24],[119,32,132,34],[41,42,43,44]])*/
1212 	incrsm: function(rows,cols,mat) {
1213 		var rows = rows.theArray || rows;
1214 		var cols = cols.theArray || cols;
1215 		var nr = rows.length;
1216 		var nc = cols.length;
1217 		if (mat.nRows != nr || mat.nCols != nc) { return; }
1218 		var m = mat.theArray;
1219 		for (var r=0; r<nr; r++) {
1220 			for (var c=0; c<nc; c++) { this.theArray[rows[r]][cols[c]] += m[r][c]; }
1221 		}
1222 	},
1223 
1224 	/** Decrement submatrix at defined positions of receiver
1225 	* @param {[floats]|Vector} rows array containing rows indices to be decrementes - numbering from 0
1226 	* @param {[floats]|Vector} cols array containing columns indices to be decremented - numbering from 0
1227 	* @param {Matrix} mat matrix to be decremented on desired positions
1228 	* @example m = mat([[11,12,13,14],[21,22,23,24],[31,32,33,34],[41,42,43,44]]);
1229 	* m.decrsm([1,2],[0,2],mat([[66,77],[88,99]]));
1230 	* // m = Matrix([11,12,13,14],[-45,22,-54,24],[-57,32,-66,34],[41,42,43,44]])*/
1231 	decrsm: function(rows,cols,mat) {
1232 		var rows = rows.theArray || rows;
1233 		var cols = cols.theArray || cols;
1234 		var nr = rows.length;
1235 		var nc = cols.length;
1236 		if (mat.nRows != nr || mat.nCols != nc) { return; }
1237 		var m = mat.theArray;
1238 		for (var r=0; r<nr; r++) {
1239 			for (var c=0; c<nc; c++) { this.theArray[rows[r]][cols[c]] -= m[r][c]; }
1240 		}
1241 	},
1242 
1243 	/** Returns copy of receiver
1244 	* @returns {Matrix} copy of receiver
1245 	* @example m1 = mat([[11,12],[21,22]]);
1246 	* m2 = m1;
1247 	* m3 = m1.copy();
1248 	* m1.set(1,0,6);
1249 	* // m1 = Matrix([[11,12],[6,22]])
1250 	* // m2 = Matrix([[11,12],[6,22]])
1251 	* // m3 = Matrix([[11,12],[21,22]])*/
1252 	copy: function() {
1253 		var ret = []
1254 		for (var r=0; r<this.nRows; r++) { ret[r] = this.theArray[r].slice(); }
1255 		return Matrix.create(ret);
1256 	},
1257 
1258 	/** Returns vector containing receiver's diagonal elements
1259 	* @returns {Vector} vector containing receiver's diagonal elements
1260 	* @example m = mat([[1,2,3],[4,5,6],[7,8,9]]);
1261 	* v = m.diag(); // v = Vector([1,5,9])*/
1262 	diagonalToVector: function() {
1263 		if (!this.isSquare()) { return null; }
1264 		var ret = [];
1265 		for (var r=0; r<this.nRows; r++) { ret[r] = this.theArray[r][r]; }
1266 		return Vector.create(ret);
1267 	},
1268 
1269 	/** Alias for diagonalToVector(), see {@link Matrix#diagonalToVector}*/
1270 	diag: function() { return this.diagonalToVector(); },
1271 
1272 	/** Returns string representation of receiver
1273 	* @returns {string} string representation of receiver
1274 	* @example m = mat([[1,2,3],[4,5,6],[7,8,9]]);
1275 	* alert(m); // alerts "Matrix([[1,2,3],[4,5,6],[7,8,9]])"*/
1276 	toString: function() {
1277 		var nr = this.nRows;
1278 		var nc = this.nCols;
1279 		var ret = "Matrix([[ "
1280 		if (nr == 0) { return ret+"])"; }
1281 		if (nc == 0) {
1282 			for (var r=0; r<nr-1; r++) {
1283 				ret += " [],";
1284 			}
1285 			return ret + " ])";
1286 		}
1287 		for (var r=0; r<nr-1; r++) {
1288 			for (var c=0; c<nc-1; c++) { ret += this.theArray[r][c]+", "; }
1289 			ret += this.theArray[r][nc-1]+" ], [ ";
1290 		}
1291 		for (var c=0; c<nc-1; c++) { ret += this.theArray[nr-1][c]+", "; }
1292 		ret += this.theArray[nr-1][nc-1]+" ]])"
1293 		return ret;
1294 	},
1295 
1296 	/** Resize receiver according to given size (delete extra elements or add zero elements)
1297 	* @param {int} nRows new number of rows
1298 	* @param {int} nCols new number of columns
1299 	* @example m1 = mat([[11,12,13,14],[21,22,23,24],[31,32,33,34],[41,42,43,44]]);
1300 	* m2 = mat([[11,12],[21,22]]);
1301 	* m1.resize(3,3); // m1 = Matrix([[11,12,13],[21,22,23],[31,32,33]])
1302 	* m2.resize(3,3); // m2 = Matrix([[11,12,0],[21,22,0],[0,0,0]])*/
1303 	resize: function(nRows,nCols) {
1304 		if (this.nRows < nRows) {
1305 			for (var r=this.nRows; r<nRows; r++) {
1306 				this.setRow(r,Vector.Zeros(this.nCols));
1307 			}
1308 			this.nRows = nRows;
1309 		}
1310 		if (this.nRows > nRows) {
1311 			this.theArray = this.theArray.slice(0,nRows);
1312 			this.nRows = nRows;
1313 		}
1314 		if (this.nCols < nCols) {
1315 			for (var r=0; r<this.nRows; r++) {
1316 				for (var c=this.nCols; c<nCols; c++) {
1317 					this.theArray[r][c] = 0.;
1318 				}
1319 			}
1320 			this.nCols = nCols;
1321 		}
1322 		if (this.nCols > nCols) {
1323 			for (var r=0; r<this.nRows; r++) {
1324 				this.theArray[r] = this.theArray[r].slice(0,nCols);
1325 			}
1326 			this.nCols = nCols;
1327 		}
1328 	},
1329 
1330 	/** Returns resized copy of receiver according to given size (delete extra elements or add zero elements)
1331 	* @param {int} nRows new number of rows
1332 	* @param {int} nCols new number of columns
1333 	* @returns {Matrix} resized copy of receiver
1334 	* @example m1 = mat([[11,12,13],[21,22,23],[31,32,33]]);
1335 	* m2 = m1.resized(2,4); // m2 = Matrix([[11,12,13,0],[21,22,23,0]])
1336 	* m3 = m1.resized(4,2); // m3 = Matrix([[11,12],[21,22],[31,32],[0,0]])*/
1337 	resized: function(nRows,nCols) {
1338 		var ret = this.copy();
1339 		ret.resize(nRows,nCols);
1340 		return ret;
1341 	},
1342 
1343 	/** Appends vector(s)/matrix as row(s) to receiver
1344 	* @param {Vector|Matrix|[Vectors]|[Matrices]} rows new row(s) to be appended
1345 	* @example m = mat([[1,2],[3,4]]);
1346 	* m.appendRows(vec([7,6])); // m = Matrix([[1,2],[3,4],[7,6]])
1347 	* m.appendRows(mat([[1,3],[2,4]])); // m = Matrix([[1,2],[3,4],[7,6],[1,3],[2,4]])
1348 	* m.appendRows([vec([2,1]),vec([33,44])]); // m = Matrix([[1,2],[3,4],[7,6],[1,3],[2,4],[2,1],[33,44]])
1349 	* m.appendRows([mat([[2,1],[4,3]]),mat([[99,88],[77,66]])]); // m = Matrix([[1,2],[3,4],[7,6],[1,3],[2,4],[2,1],[33,44],[2,1],[4,3],[99,88],[77,66]])*/
1350 	appendRows: function(rows) {
1351 		if (rows instanceof Vector) {
1352 			if (rows.nItems != this.nCols) { return; }
1353 			this.theArray[this.nRows] = rows.theArray.slice();
1354 			this.nRows++;
1355 			return;
1356 		}
1357 		if (rows instanceof Matrix) {
1358 			if (rows.nCols != this.nCols) { return; }
1359 			for (var r=0; r<rows.nRows; r++) {
1360 				this.theArray[this.nRows] = rows.theArray[r].slice();
1361 				this.nRows++;
1362 			}
1363 			return;
1364 		}
1365 		if (rows instanceof Array) {
1366 			for (var i=0; i<rows.length; i++) { this.appendRows(rows[i]); }
1367 		}
1368 	},
1369 
1370 	/** Appends vector(s)/matrix as column(s) to receiver
1371 	* @param {Vector|Matrix|[Vectors]|[Matrices]} rows new row(s) to be appended
1372 	* @example m = mat([[1,2],[3,4]]);
1373 	* m.appendCols(vec([7,6])); // m = Matrix([[1,2,7],[3,4,6]])
1374 	* m.appendCols(mat([[1,3],[2,4]])); // m = Matrix([[1,2,7,1,3],[3,4,6,2,4]])
1375 	* m.appendCols([vec([2,1]),vec([33,44])]); // m = Matrix([[1,2,7,1,3,2,33],[3,4,6,2,4,1,44]])
1376 	* m.appendCols([mat([[2,1],[4,3]]),mat([[99,88],[77,66]])]); // m = Matrix([[1,2,7,1,3,2,33,2,1,99,88],[3,4,6,2,4,1,44,4,3,77,66]])*/
1377 	appendCols: function(cols) {
1378 		if (cols instanceof Vector) {
1379 			if (cols.nItems != this.nRows) { return; }
1380 			for (var r=0; r<this.nRows; r++) { this.theArray[r][this.nCols] = cols.theArray[r]; }
1381 			this.nCols++;
1382 			return;
1383 		}
1384 		if (cols instanceof Matrix) {
1385 			if (cols.nRows != this.nRows) { return; }
1386 			for (var r=0; r<cols.nRows; r++) {
1387 				for (var c=0; c<cols.nCols; c++) { this.theArray[r][this.nCols+c] = cols.theArray[r][c]; }
1388 			}
1389 			this.nCols += cols.nCols;
1390 			return;
1391 		}
1392 		if (cols instanceof Array) {
1393 			for (var i=0; i<cols.length; i++) { this.appendCols(cols[i]); }
1394 		}
1395 	},
1396 
1397 	/** Returns row permutation matrix using implicit partial pivoting
1398 	* @param {bool} [saveOrig=true] if true, returns permutated copy of receiver. If false, permutate receiver and return this
1399 	* @Returns {[Matrix,[ints]]} permutated matrix and array containing indices of original matrix according to position in the permutated one ( such that this.rowPermutation(indx) = ret )
1400 	* @example m1 = mat([[1,2,4,9],[1,8,1,1],[9,4,5,3],[1,2,6,2]]);
1401 	* m2 = m1.implicitPartialPivotPermutation();
1402 	* // m2[0] = Matrix([[9,4,5,3],[1,8,1,1],[1,2,6,2],[1,2,4,9]])
1403 	* // m2[1] = [2,1,3,0]
1404 	* // m1 = Matrix([[1,2,4,9],[1,8,1,1],[9,4,5,3],[1,2,6,2]])
1405 	* m3 = m1.rowPermutation(m2[1]); // m3 = Matrix([[9,4,5,3],[1,8,1,1],[1,2,6,2],[1,2,4,9]])
1406 	* m4 = m2[0].rowPermutation(m2[1],true); // m4 = Matrix([[1,2,4,9],[1,8,1,1],[9,4,5,3],[1,2,6,2]])
1407 	* m1 = m1.implicitPartialPivotPermutation(false)[0];
1408 	* // m1 = Matrix([[9,4,5,3],[1,8,1,1],[1,2,6,2],[1,2,4,9]])*/
1409 	implicitPartialPivotPermutation: function(saveOrig) {
1410 		var saveOrig = saveOrig==undefined? true : saveOrig;
1411 		var n = this.nRows;
1412 		var ret = saveOrig? this.copy() : this;
1413 		var vv = [];
1414 		var indx = range(n);
1415 		var big, i, j, k;
1416 		for (i=0; i<n; i++) {
1417 			big = 0.;
1418 			for (j=0; j<n; j++) {
1419 				if ((temp=Math.abs(ret.theArray[i][j])) > big) { big=temp; }
1420 			}
1421 			if (big == 0.0) { return null; }
1422 			vv[i]=1.0/big;
1423 		}
1424 		for (k=0; k<n; k++) {
1425 			big=0.0;
1426 			for (i=k; i<n; i++) {
1427 				temp = vv[i]*Math.abs(ret.theArray[i][k]);
1428 				if (temp > big) {
1429 					big = temp;
1430 					imax = i;
1431 				}
1432 			}
1433 			if (k != imax) {
1434 				ret.swapRows(k,imax);
1435 				vv[imax]=vv[k];
1436 				temp = indx[k]
1437 				indx[k] = imax;
1438 				indx[imax] = temp;
1439 			}
1440 		}
1441 		return [ret,indx];
1442 	},
1443 	
1444 	/** Returns vector x as a solution of this*ret = vec, receiver is assumed to be lower triangular matrix
1445 	* @param {Vector} vec right hand side
1446 	* @param {bool} [saveOrig=true] if true, returns vec will be unchanged and new vector will be returned. If false, solution will be saved to vec and vec will be returned
1447 	* @Returns {Vector} solution of this*ret = vec
1448 	* @example a = mat([[1,0,0,0],[2,3,0,0],[4,5,6,0],[7,8,9,10]]);
1449 	* y = vec([4,17,43,80]);
1450 	* x = a.forwardSubstitution(y);
1451 	* // x = Vector([4,3,2,1])
1452 	* // y = Vector([4,17,43,61])
1453 	* check = a.mul(x); // check = Vector([4,17,43,61])
1454 	* // x = Vector([4,3,2,1])
1455 	* // y = Vector([4,17,43,61])
1456 	* yy - y.copy();
1457 	* x = a.forwardSubstitution(yy,false);
1458 	* // x = Vector([4,3,2,1])
1459 	* // yy = Vector([4,3,2,1])*/
1460 	forwardSubstitution: function(vec,saveOrig) {
1461 		if (!this.isSquare() || !this.canMultiplyVec(vec)) { return null; }
1462 		var saveOrig = saveOrig==undefined? true : saveOrig;
1463 		var temp;
1464 		var n = this.nRows;
1465 		var ret = saveOrig? vec.copy() : vec;
1466 		var i, j;
1467 		for (var i=0; i<n; i++) {
1468 			temp = ret.theArray[i];
1469 			for (var j=0; j<i; j++) {
1470 				temp -= this.theArray[i][j]*ret.theArray[j];
1471 			}
1472 			ret.theArray[i] = temp/this.theArray[i][i];
1473 		}
1474 		return ret;
1475 	},
1476 
1477 	/** Returns vector x as a solution of this*ret = vec, receiver is assumed to be upper triangular matrix
1478 	* @param {Vector} vec right hand side
1479 	* @param {bool} [saveOrig=true] if true, returns vec will be unchanged and new vector will be returned. If false, solution will be saved to vec and vec will be returned
1480 	* @Returns {Vector} solution of this*ret = vec
1481 	* @example a = mat([[1,2,3,4],[0,5,6,7],[0,0,8,9],[0,0,0,10]]);
1482 	* y = vec([20,34,25,10]);
1483 	* x = a.forwardSubstitution(y);
1484 	* // x = Vector([4,3,2,1])
1485 	* // y = Vector([20,34,25,10])
1486 	* check = a.mul(x); // check = Vector([20,34,25,10])
1487 	* // x = Vector([4,3,2,1])
1488 	* // y = Vector([20,34,25,10])
1489 	* yy - y.copy();
1490 	* x = a.forwardSubstitution(yy,false);
1491 	* // x = Vector([4,3,2,1])
1492 	* // yy = Vector([4,3,2,1])*/
1493 	backwardSubstitution: function(vec,saveOrig) {
1494 		if (!this.isSquare() || !this.canMultiplyVec(vec)) { return null; }
1495 		var saveOrig = saveOrig==undefined? true : saveOrig;
1496 		var temp;
1497 		var n = this.nRows;
1498 		var ret = saveOrig? vec.copy() : vec;
1499 		var i, j;
1500 		for (i=n-1; i>=0; i--) {
1501 			temp = ret.theArray[i];
1502 			for (j=i+1; j<n; j++) {
1503 				temp -= this.theArray[i][j]*ret.theArray[j];
1504 			}
1505 			ret.theArray[i] = temp/this.theArray[i][i];
1506 		}
1507 		return ret;
1508 	},
1509 
1510 	/** Returns vector as a solution of system of linear equations using gaussian elimination method (this * ret = rhs --> ret )
1511 	* @param {Vector} rhs vector of right hand sides
1512 	* @param {int} [pivoting=JSM_PARTPIVOT] what type of pivoting to use. JSM_NOPIVOT stands for no pivoting, JSM_PARTPIVOT for implicit partial pivoting (only row interchanges)
1513 	* @returns {Vector} vector of solution
1514 	* @example a = mat([[1,2,9],[8,3,2],[3,7,3]])
1515 	* b = vec([32,20,26]);
1516 	* x = a.gaussianElimination(b) // x = Vector([1,2,3])
1517 	* x = a.gaussianElimination(b,JSM_PARTPIVOT); // x = Vector([1,2,3])
1518 	* a.gaussianElimination(b,JSM_NOPIVOT,false);
1519 	* // a = Matrix([[1,2,9],[8,-13,-70],[3,1,-29.384615384615387]])
1520 	* // b = Vector([1,2,3])*/
1521 	gaussianElimination: function(rhs,pivoting,saveOrig) {
1522 		if (!this.canMultiplyVec(rhs) || !this.isSquare()) { return null; }
1523 		var pivoting = pivoting || JSM_PARTPIVOT;
1524 		var saveOrig = saveOrig==undefined? true : saveOrig;
1525 		var n = this.nRows;
1526 		var i, j, k;
1527 		if (pivoting == JSM_NOPIVOT) {
1528 			var a = saveOrig? this.copy() : this;
1529 			var b = saveOrig? rhs.copy() : rhs;
1530 			for (k=0; k<n-1; k++) {
1531 				akk = a.theArray[k][k];
1532 				for (i=k+1; i<n; i++) {
1533 					for (j=k+1; j<n; j++) {
1534 						a.theArray[i][j] -= a.theArray[k][j]*a.theArray[i][k]/akk;
1535 					}
1536 					b.theArray[i] -= b.theArray[k]*a.theArray[i][k]/akk;
1537 				}
1538 			}
1539 			return a.backwardSubstitution(b,false);
1540 		}
1541 		if (pivoting == JSM_PARTPIVOT) {
1542 			var a = this.implicitPartialPivotPermutation(saveOrig);
1543 			return a[0].gaussianElimination((saveOrig? rhs.copy() : rhs).itemPermutation(a[1]),JSM_NOPIVOT,false);
1544 		}
1545 	},
1546 
1547 	/** Returns matrix, whose columns are solutions of system of equations this*ret = rhs
1548 	* @param {Matrix,[Vectors],Vector} rhs matrix/vector/array of vectors representing right hand sides
1549 	* @param {int} [pivoting=JSM_PARTPIVOT] what type of pivoting to use. JSM_NOPIVOT stands for no pivoting, JSM_PARTPIVOT for implicit partial pivoting (only row interchanges)
1550 	* @param {bool} [saveOrig=true] if true, receiver is not changed. If false, solution will be saved to rhs and rhs will be returned
1551 	* @returns {Matrix} matrix, whose columns are solution for particular right hand sides
1552 	* @example a = mat([[1,2,9],[8,3,2],[3,7,3]]);
1553 	* b1 = vec([32,20,26]);
1554 	* b2 = vec([16,32,26]);
1555 	* b3 = [b1.copy(),b2.copy()];
1556 	* b4 = mat([b1.toArray(),b2.toArray()]);
1557 	* x1 = a.gaussJordanElimination(b1);
1558 	* // x1 = Vector([ 1, 2, 3 ])
1559 	* x2 = a.gaussJordanElimination(b2);
1560 	* // x2 = Vector([ 3.0000000000000018, 2, 1 ])
1561 	* x3 = a.gaussJordanElimination(b3);
1562 	* // x3 = Vector([ 1, 2, 3 ]) ,Vector([ 3.0000000000000018, 2, 1 ])
1563 	* x4 = a.gaussJordanElimination(b4);
1564 	* // x4 = Matrix([[ 1, 3.0000000000000018 ], [ 2, 2 ], [ 3, 1 ]])
1565 	* x5 = a.gaussJordanElimination(b1,JSM_PARTPIVOT);;
1566 	* // x5 = Vector([ 1, 2, 3 ])
1567 	* x6 = a.gaussJordanElimination(b2,JSM_PARTPIVOT);
1568 	* // x6 = Vector([ 3, 2, 1 ])
1569 	* x7 = a.gaussJordanElimination(b3,JSM_PARTPIVOT);
1570 	* // x7 = Vector([ 1, 2, 3 ]) ,Vector([ 3, 2, 1 ])
1571 	* x8 = a.gaussJordanElimination(b4,JSM_PARTPIVOT);
1572 	* // x8 = Matrix([[ 1, 3 ], [ 2, 2 ], [ 3, 1 ]])
1573 	* a.gaussJordanElimination(b4,JSM_NOPIVOT,false);
1574 	* // b4 = Matrix([[ 1, 3.0000000000000018 ], [ 2, 2 ], [ 3, 1 ]])*/
1575 	gaussJordanElimination: function(rhs,pivoting,saveOrig) {
1576 		if (!this.isSquare) { return null; }
1577 		var rhs = rhs || null;
1578 		if (rhs == null) { return null; }
1579 		var rhsInstance = (rhs instanceof Vector)? 1 : ((rhs instanceof Array)? 2 : ((rhs instanceof Matrix)? 3 : 4));
1580 		if (!(rhsInstance==1 || rhsInstance==2 || rhsInstance==3)) { return null; }
1581 		var pivoting = pivoting || JSM_PARTPIVOT;
1582 		var saveOrig = saveOrig==undefined? true : saveOrig;
1583 		var i, j, k, akk;
1584 		var n = this.nRows;
1585 		var nrhs = rhsInstance==2? rhs.length : (rhsInstance==3? rhs.nCols : 0);
1586 		if (pivoting == JSM_NOPIVOT) {
1587 			var a = saveOrig? this.copy() : this;
1588 			var b;
1589 			if (rhsInstance==1 || rhsInstance==3) { b = saveOrig? rhs.copy() : rhs; }
1590 			else {
1591 				b = [];
1592 				for (i=0; i<nrhs; i++) { b[i] = saveOrig? rhs[i].copy() : rhs[i]; }
1593 			}
1594 			for (k=0; k<n; k++) {
1595 				akk = a.theArray[k][k];
1596 				for (i=k+1; i<n; i++) {
1597 					for (j=k+1; j<n; j++) {
1598 						a.theArray[i][j] -= a.theArray[k][j]*a.theArray[i][k]/akk;
1599 					}
1600 					switch (rhsInstance) {
1601 						case 1: b.theArray[i] -= b.theArray[k]*a.theArray[i][k]/akk; break;
1602 						case 2: for (j=0; j<nrhs; j++) { b[j].theArray[i] -= b[j].theArray[k]*a.theArray[i][k]/akk; } break;
1603 						case 3: for (j=0; j<nrhs; j++) { b.theArray[i][j] -= b.theArray[k][j]*a.theArray[i][k]/akk; } break;
1604 					}
1605 				}
1606 			}
1607 			for (k=n-1; k>=0; k--) {
1608 				akk = a.theArray[k][k];
1609 				for (i=k-1; i>=0; i--) {
1610 					for (j=n-1; j>k; j--) {
1611 						a.theArray[i][j] -= a.theArray[k][j]*a.theArray[i][k]/akk;
1612 					}
1613 					switch (rhsInstance) {
1614 						case 1: b.theArray[i] -= b.theArray[k]*a.theArray[i][k]/akk; break;
1615 						case 2: for (j=0; j<nrhs; j++) { b[j].theArray[i] -= b[j].theArray[k]*a.theArray[i][k]/akk; } break;
1616 						case 3: for (j=0; j<nrhs; j++) { b.theArray[i][j] -= b.theArray[k][j]*a.theArray[i][k]/akk; } break;
1617 					}
1618 				}
1619 			}
1620 			for (k=0; k<n; k++) {
1621 				akk = a.theArray[k][k];
1622 				switch (rhsInstance) {
1623 					case 1: b.theArray[k] /= akk; break;
1624 					case 2: for (j=0; j<nrhs; j++) { b[j].theArray[k] /= akk; } break;
1625 					case 3: for (j=0; j<nrhs; j++) { b.theArray[k][j] /= akk; } break;
1626 				}
1627 			}
1628 			return b;
1629 		}
1630 		if (pivoting == JSM_PARTPIVOT) {
1631 			var a = this.implicitPartialPivotPermutation(saveOrig);
1632 			var temp;
1633 			switch (rhsInstance) {
1634 				case 1: temp = saveOrig? rhs.copy() : rhs; temp.permuteItems(a[1]); break;
1635 				case 2:
1636 					temp = [];
1637 					for (i=0; i<nrhs; i++) {
1638 						temp[i] = saveOrig? rhs[i].copy() : rhs[i];
1639 						temp[i].permuteItems(a[1]);
1640 					}
1641 					break;
1642 				case 3:
1643 					temp = saveOrig? rhs.copy() : rhs; temp.permuteRows(a[1]); break;
1644 			}
1645 			return a[0].gaussJordanElimination(temp,JSM_NOPIVOT,false);
1646 		}
1647 	},
1648 
1649 	/** Returns lower triangular matrix of Cholesky's (LLT) decomposition of receiver. Receiver must be square, symmetric and positive definite. ( ret * ret^T = this )
1650 	* @returns {Matrix} lower triangular matrix
1651 	* @example a = mat([[1,2,4],[2,13,23],[4,23,77]]);
1652 	* l = a.choleskyDecomposition(); // l = Matrix([[1,0,0],[2,3,0],[4,5,6]])
1653 	* check = l.x(l.T()); // check = Matrix([[1,2,4],[2,13,23],[4,23,77]]);*/
1654 	choleskyDecomposition: function() {
1655 		if (!this.isSquare()) { return null; }
1656 		if (!this.isSymmetric()) { return null; }
1657 		var n = this.nRows;
1658 		var ret = Matrix.Zeros(n,n);
1659 		var retii, temp, i, j, k;
1660 		for (i=0; i<n; i++) {
1661 			retii = this.theArray[i][i]
1662 			for (k=0; k<i; k++) { retii -= ret.theArray[i][k]*ret.theArray[i][k]; }
1663 			if (retii<=0.) { return null; }
1664 			retii = Math.sqrt(retii);
1665 			ret.theArray[i][i] = retii;
1666 			for (j=i; j<n; j++) {
1667 				temp = this.theArray[i][j];
1668 				for (k=0; k<i; k++) { temp -= ret.theArray[i][k]*ret.theArray[j][k]; }
1669 				ret.theArray[j][i] = temp/retii;
1670 			}
1671 		}
1672 		return ret;
1673 	},
1674 
1675 	/** Alias for Cholesky decomposition, see {@link Matrix#choleskyDecomposition}*/
1676 	chol: function() { return this.choleskyDecomposition(); },
1677 
1678 	/** Alias for Cholesky decomposition, see {@link Matrix#choleskyDecomposition}*/
1679 	lltDecomposition: function() { return this.choleskyDecomposition(); },
1680 
1681 	/** Returns lower (L) and upper (U) triangular matrix of the receiver such that L*U=this. Diagonal elements of L are all 1. Receiver must be square.
1682 	* @param {int} [pivoting=JSM_NOPIVOT] what type of pivoting to use. JSM_NOPIVOT stands for no pivoting, JSM_PARTPIVOT for implicit partial pivoting (only row interchanges)
1683 	* @returns {[Matrix,Matrix]} [L,U], lower and upper triangular matrices
1684 	* @example a = mat([[6,5,4],[12,13,10],[18,27,21]]);
1685 	* lu = a.luDecomposition();
1686 	* l = lu[0]; // l = Matrix([[1,0,0],[2,1,0],[3,4,1]])
1687 	* u = lu[1]; // u = Matrix([[6,5,4],[0,3,2],[0,0,1]])
1688 	* check = l.x(u); // check = Matrix([[6,5,4],[12,13,10],[18,27,21]])*/
1689 	luDecomposition: function(pivoting) {
1690 		if (!this.isSquare()) { return null; }
1691 		var pivoting = pivoting || JSM_NOPIVOT;
1692 		var n = this.nRows;
1693 		var l = Matrix.Zeros(n,n);
1694 		var u = Matrix.Zeros(n,n);
1695 		var i, j, k, imax;
1696 		var temp;
1697 		if (pivoting == JSM_NOPIVOT) {
1698 			for (k=0; k<n; k++) {
1699 				l.theArray[k][k] = 1.;
1700 				for (j=k; j<n; j++) {
1701 					temp = this.theArray[k][j];
1702 					for (i=0; i<k; i++) {
1703 						temp -= l.theArray[k][i]*u.theArray[i][j];
1704 					}
1705 					u.theArray[k][j] = temp;
1706 				}
1707 				for (j=k+1; j<n; j++) {
1708 					temp = this.theArray[j][k]
1709 					for (i=0; i<k; i++) {
1710 						temp -= l.theArray[j][i]*u.theArray[i][k]
1711 					}
1712 					l.theArray[j][k] = temp/u.theArray[k][k]
1713 				}
1714 			}
1715 			return [l,u]
1716 		}
1717 		if (pivoting == JSM_PARTPIVOT) {
1718 			var a = this.implicitPartialPivotPermutation()
1719 			var ret = a[0].luDecomposition(JSM_NOPIVOT);
1720 			ret[2] = a[1];
1721 			return ret;
1722 		}
1723 	},
1724 
1725 	/** Returns lower triangular (L), diagonal (D) and upper triangular (U) matrix of the receiver such that L*D*U=this. Diagonal elements of both L and U are all 1. Receiver must be square.
1726 	* @param {int} [pivoting=JSM_NOPIVOT] what type of pivoting to use. JSM_NOPIVOT stands for no pivoting, JSM_PARTPIVOT for implicit partial pivoting (only row interchanges)
1727 	* @param {bool} [retDiagAsVector = false] if true, d is returned as vector. If false, d is returned as diagonal matrix
1728 	* @returns {[Matrix,Matrix|Vector,Matrix]} [L,D,U], lower, diagonal and upper triangular matrices
1729 	* @example a = mat([[12,10,8],[24,29,22],[36,66,52]]);
1730 	* ldu = a.lduDecomposition();
1731 	* l = ldu[0]; // l = Matrix([[1,0,0],[2,1,0],[3,4,1]])
1732 	* d = ldu[1]; // d = Matrix([[2,0,0],[0,3,0],[0,0,4]])
1733 	* u = ldu[2]; // u = Matrix([[6,5,4],[0,3,2],[0,0,1]])
1734 	* check = l.x(d).x(u) // check = Matrix([[12,10,8],[24,29,22],[36,66,52]])*/
1735 	lduDecomposition: function(pivoting,retDiagAsVector) {
1736 		if (!this.isSquare()) { return null; }
1737 		var pivoting = pivoting || JSM_NOPIVOT;
1738 		var retDiagAsVector = retDiagAsVector || false;
1739 		if (pivoting == JSM_NOPIVOT) {
1740 			var n = this.nRows;
1741 			var l = zeros(n,n);
1742 			var d = zeros(n);
1743 			var u = zeros(n,n);
1744 			var temp;
1745 			for (var i=0; i<n; i++) {
1746 				l.theArray[i][i] = 1.;
1747 				u.theArray[i][i] = 1.;
1748 				for (var j=0; j<i; j++) {
1749 					temp = this.theArray[i][j];
1750 					for (var k=0; k<j; k++) {
1751 						temp -= l.theArray[i][k]*d.theArray[k]*u.theArray[k][j];
1752 					}
1753 					l.theArray[i][j] = temp/d.theArray[j];
1754 				}
1755 				temp = this.theArray[i][i];
1756 				for (var k=0; k<i; k++) {
1757 					temp -= l.theArray[i][k]*d.theArray[k]*u.theArray[k][i];
1758 				}
1759 				d.theArray[i] = temp;
1760 				for (var j=i+1; j<n; j++) {
1761 					temp = this.theArray[i][j];
1762 					for (var k=0; k<i; k++) {
1763 						temp -= l.theArray[i][k]*d.theArray[k]*u.theArray[k][j];
1764 					}
1765 					u.theArray[i][j] = temp/d.theArray[i];
1766 				}
1767 			}
1768 			if (retDiagAsVector) { return [l,d,u]; }
1769 			return [l,d.toDiagonalMatrix(),u];
1770 		}
1771 		if (pivoting = JSM_PARTPIVOT) {
1772 			var a = this.implicitPartialPivotPermutation();
1773 			var ret = a.lduDecomposition(JSM_NOPIVOT,retDiagAsVector,false);
1774 			ret[3] = a[1];
1775 			return ret;
1776 		}
1777 	},
1778 
1779 	/** Returns orthogonal matrix Q^T and upper triangular matrix R of QR decomposition of receiver such that Q*R=this.
1780 	* @param {bool} [saveOrig=true] if true, receiver is not changed. If false, solution (R matrix) will be saved to this and this will be returned
1781 	* @returns {[Matrix,Matrix]} Q^T and R of QR decomposition of receiver
1782 	* @example a = mat([[1,2,9],[8,3,4],[3,7,1]]);
1783 	* qr = a.qrDecomposition();
1784 	* qt = qr[0]; // qt = Matrix([[ -0.1162, -0.9299, -0.3487 ], [ 0.2407, -0.3670, 0.8985 ], [ -0.9636, 0.0205, 0.2665 ]])
1785 	* r = qr[1]; // r = Matrix([[ -8.6023, -5.4636, -5.1148 ], [ 0, 5.6699, 1.5968 ], [ 0, 0, -8.3239 ]])
1786 	* check = q.T().x(r); // check = Matrix([[1,2,9],[8,3,4],[3,7,1]])
1787 	* o = q.T().x(q); // o = Matrix([[1,0,0],[0,1,0],[0,0,1]])*/
1788 	qrDecomposition: function(saveOrig) {
1789 		if (!this.isSquare()) { return null; }
1790 		var saveOrig = saveOrig==undefined? true : saveOrig;
1791 		var n = this.nRows;
1792 		var qt = Matrix.Zeros(n,n);
1793 		var r = saveOrig? this.copy() : this;
1794 		var c = [];
1795 		var d = [];
1796 		var scale, sigma, sum, tau, sing;
1797 		for (k=0; k<n-1; k++) {
1798 			scale=0.0;
1799 			for (i=k;i<n;i++) scale = Math.max(scale, Math.abs(r.theArray[i][k]));
1800 			if (scale == 0.0) { // Singular case.
1801 				sing = true;
1802 				c[k] = 0.0;
1803 				d[k] = 0.0;
1804 			}
1805 			else { // Form Qk and Qk A.
1806 				for (i=k; i<n; i++) { r.theArray[i][k] /= scale; }
1807 				sum = 0.;
1808 				for (i=k; i<n; i++) { sum += (r.theArray[i][k]*r.theArray[i][k]); }
1809 				sigma = Math.sqrt(sum)*(r.theArray[k][k]>=0.? 1. : -1.);
1810 				r.theArray[k][k] += sigma;
1811 				c[k] = sigma*r.theArray[k][k];
1812 				d[k] = -scale*sigma;
1813 				for (j=k+1; j<n; j++) {
1814 					sum = 0.;
1815 					for (i=k; i<n; i++) { sum += r.theArray[i][k]*r.theArray[i][j]; }
1816 					tau = sum/c[k];
1817 					for (i=k; i<n; i++) { r.theArray[i][j] -= tau*r.theArray[i][k]; }
1818 				}
1819 			}
1820 		}
1821 		d[n-1] = r.theArray[n-1][n-1];
1822 		if (d[n-1] == 0.0) { sing = true; }
1823 		for (i=0; i<n; i++) { // Form QT explicitly.
1824 			for (j=0; j<n; j++) { qt.theArray[i][j] = 0.; }
1825 			qt.theArray[i][i] = 1.0;
1826 		}
1827 		for (k=0; k<n-1; k++) {
1828 			if (c[k] != 0.0) {
1829 				for (j=0; j<n; j++) {
1830 					sum = 0.0;
1831 					for (i=k ;i<n; i++) {
1832 						sum += r.theArray[i][k]*qt.theArray[i][j];
1833 					}
1834 					sum /= c[k];
1835 					for (i=k;i<n;i++) {
1836 						qt.theArray[i][j] -= sum*r.theArray[i][k];
1837 					}
1838 				}
1839 			}
1840 		}
1841 		for (i=0; i<n; i++) { // Form R explicitly.
1842 			r.theArray[i][i] = d[i];
1843 			for (j=0; j<i; j++) { r.theArray[i][j] = 0.0; }
1844 		}
1845 		return [qt,r];
1846 	},
1847 
1848 	/** Returns inversion of receiver
1849 	* @param {int} [method=JSM_GAUSSJORDAN] method used for solution. Options are JSM_GAUSSJORDAN for Gauss-Jordan method, JSM_LU for solution with LU decomposition
1850 	* @param {[Matrices]} [precompDecomps=undefined] precomputed matrix decompositions if we want to se some
1851 	* @returns {Matrix} inversion of receiver
1852 	* @example a = mat([[2,2,1],[2,3,0.5],[1,0.5,2]]);
1853 	* b = a.inversed(); // b = Matrix([[2.3,-1.4,-0.8],[-1.4,1.2,0.4],[-0.8,0.4,0.8]])
1854 	* check = a.x(b); // check = Matrix([[1,0,0],[0,1,0],[0,0,1]])*/
1855 	inversed: function(method,precompDecomps) {
1856 		if (!this.isSquare) { return null; }
1857 		var method = method || JSM_GAUSSJORDAN;
1858 		switch (method) {
1859 			case JSM_GAUSSJORDAN: return this.gaussJordanElimination(Matrix.Identity(this.nRows,this.nRows));
1860 			default: return null;
1861 		}
1862 	},
1863 
1864 	/** Alias for inversion, see {@link Matrix#inversed}*/
1865 	inv: function(method,precompDecomps) { return this.inversed(method||undefined,precompDecomps||undefined); },
1866 
1867 	/** Returns determinant of receiver.
1868 	* @param {int} [method=JSM_LU] used method. Options are JSM_LU for using LU decomposition
1869 	* @param {[Matrices]} precompDecomps precomputed matrix decompositions if we want to use some
1870 	* @returns {float} determinant of receiver
1871 	* @example a = mat([[4,2,1],[2,5,3],[1,3,6]]);
1872 	* d = a.determinant(); // d = 67*/
1873 	determinant: function(method,precompDecomps) {
1874 		if (!this.isSquare()) { return null; }
1875 		var method = method || JSM_LU;
1876 		var mats = precompDecomps || undefined
1877 		switch (method) {
1878 			case JSM_LU:
1879 				mats = precompDecomps? precompDecomps : this.luDecomposition();
1880 				var diag = mats[1].diag();
1881 				var ret = diag.theArray[0];
1882 				for (var r=1; r<this.nRows; r++) { ret *= diag.theArray[r]; }
1883 				return ret;
1884 			default: return null;
1885 		}
1886 	},
1887 
1888 	/** Alias for determinant, see {@link Matrix#determinant}*/
1889 	det: function(method,precompDecomps) { return this.determinant(method||undefined,precompDecomps||undefined); },
1890 
1891 	/** Test receiver's singularity
1892 	* @returns {bool} true if receiver is singular (if abs(this.det()) < JSM_TOL), false otherwise
1893 	* @example a = mat([[1,2,3],[2,4,6],[4,5,6]]);
1894 	* b = mat([[4,2,1],[2,5,3],[1,3,6]]);
1895 	* s1 = a.isSingular(); // s1 = true
1896 	* s2 = b.isSingular(); // s1 = false*/
1897 	isSingular: function() {
1898 		var d = this.determinant();
1899 		return isNaN(d)? true : (Math.abs(d) < JSM_TOL);
1900 	},
1901 
1902 	/** Returns vector/array of vectors/matrix as a solution of system of linear equations (this*ret=rhs --> ret). Receiver must be square. TODO: solution with LU decomposition with permutation
1903 	* @param {Vector|[Vectors]|Matrix} rhs vector of right hand sides. Array of vectors or Matrix as rhs is supported only with JSM_GAUSSJORDAN method
1904 	* @param {int} [method=JSM_GAUSS] method of the solution. Implemented methods are JSM_GAUSS for gaussian elimination, JSM_GAUSSJORDAN for Gauss-Jordan elimination (supporting more than one right hand sides in form of array of vectors or matrix with columns as rhs), JSM_LU for using LU decomposition, JSM_LDU for using LDU decomposition, JSM_CHOLESKY for using Cholesky decomposition
1905 	* @param {bool} [saveOrig=true] if true, receiver and rhs is not changed. If false, solution will be saved to rhs and rhs will be returned and receiver will be changed
1906 	* @param {[Matrices]} [precompDecomps=undefined] array of Matrices objects, used for solution using matrix decomposition as precomputed values (the decomposition is performed within solveForRhs function if args parameter is not specified)
1907 	* @returns {Vector|[Vectors]|Matrix} vector/array of vectors/matrix of solution
1908 	* @example a = mat([[1,2,9],[8,3,2],[3,7,3]]);
1909 	* b = vec([32,20,26]);
1910 	* x1 = a.solveForRhs(b); // x1 = Vector([1,2,3])
1911 	* x2 = a.solveForRhs(b,JSM_GAUSS); // x2 = Vector([1,2,3])
1912 	* x3 = a.solveForRhs(b,JSM_GAUSSJORDAN); // x3 = Vector([1,2,3])
1913 	* x4 = a.solveForRhs(b,JSM_LU); // x4 = Vector([1,2,3])
1914 	* x5 = a.solveForRhs(b,JSM_LDU); // x5 = Vector([1,2,3])
1915 	* x6 = a.solveForRhs(b,JSM_CHOLESKY); // x6 = Vector([1,2,3])
1916 	* x7 = a.solveForRhs(b,JSM_QR); // x7 = Vector([1,2,3])*/
1917 	solveForRhs: function(rhs,method,saveOrig,precompDecomps) {
1918 		var saveOrig = saveOrig==undefined? true : saveOrig;
1919 		var method = method || JSM_GAUSS;
1920 		if (method==JSM_GAUSS) { // gaussian elimination
1921 			return this.gaussianElimination(rhs,JSM_PARTPIVOT,saveOrig);
1922 		}
1923 		if (method==JSM_GAUSSJORDAN) { // gaussian elimination
1924 			return this.gaussJordanElimination(rhs,JSM_PARTPIVOT,saveOrig);
1925 		}
1926 		if (method==JSM_LU) { // use LU factorization
1927 			var lu = precompDecomps || this.luDecomposition();
1928 			var l = lu[0];
1929 			var u = lu[1];
1930 			var y;
1931 			if (rhs instanceof Vector) {
1932 				y = l.forwardSubstitution(rhs,saveOrig);
1933 				return u.backwardSubstitution(y,false);
1934 			}
1935 			if (rhs instanceof Matrix) {
1936 				var ret = saveOrig? Matrix.Zeros(this.nRows,rhs.nCols) : rhs;
1937 				for (var i=0; i<rhs.nCols; i++) {
1938 					y = l.forwardSubstitution(rhs.getCol(i),false);
1939 					ret.setCol(i,u.backwardSubstitution(y,false));
1940 				}
1941 				return ret;
1942 			}
1943 			if (rhs instanceof Array) {
1944 				return null;
1945 				// TODO
1946 			}
1947 		}
1948 		if (method==JSM_LDU) { // use LDU decomposition
1949 			var ldu = precompDecomps || this.lduDecomposition(JSM_NOPIVOT,true);
1950 			var l = ldu[0];
1951 			var d = (ldu[1] instanceof Matrix)? ldu[1].diag() : ldu[1];
1952 			var u = ldu[2];
1953 			var y = l.forwardSubstitution(rhs,saveOrig);
1954 			for (var r=0; r<this.nRows; r++) { y.theArray[r] /= d.theArray[r]; }
1955 			return u.backwardSubstitution(y,false);
1956 		}
1957 		if (method==JSM_CHOLESKY) { // use Cholesky's decomposition
1958 			var l = precompDecomps || this.choleskyDecomposition();
1959 			if (l==null) { return null; }
1960 			var y = l.forwardSubstitution(rhs,saveOrig);
1961 			return l.T().backwardSubstitution(y,false);
1962 		}
1963 		if (method==JSM_QR) { // use QR decomposition
1964 			var qr = precompDecomps || this.qrDecomposition(saveOrig);
1965 			return qr[1].backwardSubstitution(qr[0].mulv(rhs),false);
1966 		}
1967 		return null;
1968 	},
1969 	/**#@-*/
1970 }
1971 
1972 /** Constructs new Matrix from given 2D array
1973 * @param {[floats](2D)} [arry=[]] array containing elements of new matrix
1974 * @returns {Matrix} new Matrix object
1975 * @example m = Matrix.create([[1,2,3],[4,5,6],[7,8,9]]) // m = Matrix([[1,2,3],[4,5,6],[7,8,9]])*/
1976 Matrix.create = function(arry) {
1977 	var a = (arry==null)? [[]]:arry;
1978 	ret = new Matrix();
1979 	ret.fromArray(a);
1980 	return ret;
1981 }
1982 
1983 /** Constructs new diagonal matrix from given 1D array
1984 * @param {[floats]|Vector} arry array or vector containing elements of new matrix
1985 * @returns {Matrix} new Matrix object 
1986 * @example m1 = Matrix.Diagonal([1,2,3]); // m1 = Matrix([[1,0,0],[0,2,0],[0,0,3]])
1987 * m2 = Matrix.Diagonal(vec([1,2,3])); // m2 = Matrix([[1,0,0],[0,2,0],[0,0,3]])*/
1988 Matrix.Diagonal = function(arry) {
1989 	return Vector.create(arry.theArray || arry).diag();
1990 }
1991 
1992 /** Constructs new identity matrix of given size
1993 * @param {int} size size of returned matrix
1994 * @returns {Matrix} identity matri
1995 * @example m = Matrix.Identity(4) // m = Matrix([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])*/
1996 Matrix.Identity = function(size) {
1997 	var a = []
1998 	for (var i=0; i<size; i++) { a[i] = 1.; }
1999 	return Matrix.Diagonal(a);
2000 }
2001 
2002 /** Alias for Matrix.Identity(), see {@link Matrix#Identity}*/
2003 Matrix.I = function(nRows) { return Matrix.Identity(nRows); }
2004 
2005 /** Creates a matrix of given size full of zeros
2006 * @param {int} [nRows=0] number of rows
2007 * @param {int} [nCols=0] number of columns
2008 * @returns {Matrix} new matrix full of zero
2009 * @example m = Matrix.Zeros(2,3); // m = Matrix([[0,0,0],[0,0,0]])*/
2010 Matrix.Zeros = function(nRows,nCols) {
2011 	var nRows = nRows || 0;
2012 	var nCols = nCols || 0;
2013 	var a = []
2014 	for (var r=0; r<nRows; r++) {
2015 		a[r] = []
2016 		for (var c=0; c<nCols; c++) {
2017 			a[r][c] = 0.;
2018 		}
2019 	}
2020 	return Matrix.create(a);
2021 }
2022 
2023 /** Creates a matrix of given size full of ones
2024 * @param {int} [nRows=0] number of rows
2025 * @param {int} [nCols=0] number of columns
2026 * @returns {Matrix} new vector full of zero
2027 * @example m = Matrix.Ones(2,3); // m = Matrix([[1,1,1],[1,1,1]])*/
2028 Matrix.Ones = function(nRows,nCols) {
2029 	var nRows = nRows || 0;
2030 	var nCols = nCols || 0;
2031 	var a = []
2032 	for (var r=0; r<nRows; r++) {
2033 		a[r] = []
2034 		for (var c=0; c<nCols; c++) {
2035 			a[r][c] = 1.;
2036 		}
2037 	}
2038 	return Matrix.create(a);
2039 }
2040 
2041 
2042 
2043 /* **************************************************
2044 *
2045 * Initializing functions
2046 *
2047 ***************************************************/
2048 
2049 /** Returns new Matrix object from given array
2050 * @param {[floats](2D)} [arry=[]] array containing matrix elements
2051 * @returns {Matrix} new Matrix object
2052 * @example m = mat([[1,2,3],[4,5,6],[7,8,9]]) // m = Matrix([[1,2,3],[4,5,6],[7,8,9]])*/
2053 mat = function(arry) {
2054 	var arry = (arry==null)? [[]]:arry;
2055 	return Matrix.create(arry);
2056 }
2057 
2058 /** Returns new Vector object from given array
2059 * @param {[floats]} [arry=[]] array containing vector elements
2060 * @returns {Vector} new Vector object
2061 * @example v = vec([1,2,3,4]) // v = Vector([1,2,3,4])*/
2062 vec = function(arry) {
2063 	var arry = (arry==null)? []:arry;
2064 	return Vector.create(arry);
2065 }
2066 
2067 /** Returns new Vector or Matrix full of given size full of zeros
2068 * @param {int} nRows number of rows of returned object
2069 * @param {int} [nCols] if specified, new Matrix of size (nRows,nCols) is returned, new vector of size nRows otherwise
2070 * @returns {Matrix|Vector} new Matrix or Vector object
2071 * @example m = zeros(2,3); // m = Matrix([[0,0,0],[0,0,0]])
2072 * v = zeros(4) // v = Vector([0,0,0,0])*/
2073 zeros = function(nRows,nCols) {
2074 	if (nCols) { return Matrix.Zeros(nRows,nCols); }
2075 	if (nRows) { return Vector.Zeros(nRows); }
2076 	return null;
2077 }
2078 
2079 /** Returns new Vector or Matrix full of given size full of ones
2080 * @param {int} nRows number of rows of returned object
2081 * @param {int} [nCols] if specified, new Matrix of size (nRows,nCols) is returned, new vector of size nRows otherwise
2082 * @returns {Matrix|Vector} new Matrix or Vector object
2083 * @example m = zeros(2,3); // m = Matrix([[1,1,1],[1,1,1]])
2084 * v = zeros(4) // v = Vector([1,1,1,1])*/
2085 ones = function(nRows,nCols) {
2086 	if (nCols) { return Matrix.Ones(nRows,nCols); }
2087 	if (nRows) { return Vector.Ones(nRows); }
2088 	return null;
2089 }
2090 
2091 /** Returned identity matrix of given size, see {@link Matrix#Identity}
2092 * @param {int} nRows number of rows and columns of returned matrix
2093 * @returns {Matrix} nRows x nRows identity matrix
2094 * @example m = identity(3); // m = Matrix([[1,0,0],[0,1,0],[0,0,1]])*/
2095 identity = function(nRows) { return Matrix.Identity(nRows); }
2096 
2097 /** Alias for dentity(), see {@link identity}*/
2098 eye = function(nRows) { return Matrix.Identity(nRows); }
2099 
2100 
2101 /* ***********************************************************
2102 *
2103 * Other functions
2104 *
2105 ************************************************************/
2106 
2107 /** Linear system equation solver. Returns vector x as a solution of a*ret=rhs, see {@link Matrix#solveForRhs} for input desription
2108 * @param {Matrix} a
2109 * @param {Vector|[Vectors]|Matrix} rhs
2110 * @param {bool} [saveOrig=true]
2111 * @param {int} [method=JSM_GAUSS]
2112 * @param {[Matrices]} [precompDecomps]
2113 * @returns {Vector|[Vectors]|Matrix} solution x of a*x=rhs*/
2114 linSolve = function(a,rhs,saveOrig,method,precompDecomps) { return a.solveForRhs(rhs,saveOrig||undefined,method||undefined,precompDecomps||undefined); }
2115 
2116 
2117 /** Eigenvalues and eigenvectors solver. Returns first nEigModes eigenvales and eigenvectors of problem K*vi=oi^2*M*vi (oi is i-th eigenvale and vi is i-th eigenvector). Typycal example of usage is eigenvale dynamics.
2118 * @param {Matrix} K first matrix (stiffness matrix for dynamics)
2119 * @param {Matrix} M second matrix (mass matrix for dynamics)
2120 * @param {int} [nEigModes=1] number of first eigenvalues and eigenvectors to be returned
2121 * @param {int} [method=JSM_INV_IT] method of the solution. JSM_INV_IT stands for Stodola's inverse iterations methods with Gramm-Schmidt orthogonalization
2122 * @param {int} [maxiter=1000] maximum number of iterations
2123 * @returns {[[floats],[Vectors]]} [[o1,o2,...,oN],[v1,v2,...,vN]], oi is i-th eigenvale (squared eigenfrequency for dynamics), vi is i-th eigenvector. N = nEigModes
2124 * @example K = mat([[9,3,0,0],[3,8,2,0],[0,2,7,2],[0,0,2,8]]);
2125 * M = Matrix.Diagonal([3,2,4,3]);
2126 * e = eigSolve(K,M,4);
2127 * o = e[0];
2128 * v = e[1];
2129 * o1 = o[0]; // o1 = 1.2504038497315775
2130 * o2 = o[1]; // o2 = 2.279120228657416
2131 * o3 = o[2]; // o3 = 2.948867853467429
2132 * o4 = o[3]; // o4 = 4.938274734810245
2133 * v1 = v[0]; // v1 = Vector([ 0.1288306767139194, -0.22540165581364102, 0.4265175098731745, -0.20077135620035116 ])
2134 * v2 = v[1]; // v2 = Vector([ 0.4514687335612619, -0.32545467450354726, -0.11713473474653795, 0.2014979513549984 ])
2135 * v3 = v[2]; // v3 = Vector([ 0.14681878659487543, -0.007507144503266177, -0.21233717286242818, -0.5016212772448967 ])
2136 * v4 = v[3]; // v4 = Vector([ 0.3022519091588433, 0.585847242190032, 0.09630780190740544, 0.028264211960396433 ])
2137 * c1 = K.x(v1).sub(M.x(v1).x(o1)); // c1 = Vector([ 6.045241529584189e-10, -2.9052349415081835e-10, -2.091367079515294e-10, 2.697864154299623e-10 ])
2138 * c2 = K.x(v2).sub(M.x(v2).x(o2)); // c2 = Vector([ 8.74326433475403e-9, -4.933693453779142e-10, -1.5765841965276195e-8, -2.9551703084607084e-8 ])
2139 * c3 = K.x(v3).sub(M.x(v3).x(o3)); // c3 = Vector([ 4.5619911848149286e-8, 1.2227673172604536e-8, -9.32639299122684e-10, 1.3564216416739328e-8 ])
2140 * c4 = K.x(v4).sub(M.x(v4).x(o4)); // c4 = Vector([ 9.357854047209457e-9, -3.189910557921394e-10, -1.804510585401431e-8, -3.197205944438508e-8 ])*/
2141 eigSolve = function(K,M,nEigModes,method,maxiter) {
2142 	var K = K;
2143 	var M = M;
2144 	if (!K.isSquare() || !M.isSquare() || !K.isSameSizeAs(M)) { return null; }
2145 	var nEigModes = nEigModes || 1; // nEigModes first eigenvalues and eigenvectors will be returned
2146 	if (nEigModes > K.nRows) { nEigModes = K.nRows; }
2147 	var method = method || JSM_INV_IT;
2148 	var maxiter = maxiter || 1000;
2149 	if (method == JSM_INV_IT) { // Stodola's inverse iteration with Gramm-Schmidt orthogonalization
2150 		var DM = K.inv().mulm(M);
2151 		var tol = 1e-32;
2152 		var eigVals = [];
2153 		var eigVecs = [];
2154 		var eigVecsMulmM = [];
2155 		var rho, rhoRatio, rhoNew, iter;
2156 		var xk = Vector.Zeros(K.nRows);
2157 		for (var k=0; k<nEigModes; k++) {
2158 			xk.zero(); xk.set(0,1.);
2159 			iter = 0;
2160 			rhoNew = 0.;
2161 			do {
2162 				xk = DM.mulv(xk);
2163 				for (var j=0; j<k; j++) { xk.isub(eigVecs[j].mulf(eigVecsMulmM[j].dot(xk))); } // Gramm-Schmidt orthogonalization
2164 				xk.imulf(1./Math.sqrt(xk.mulm(M).dot(xk)));
2165 				rho = rhoNew;
2166 				rhoNew = (xk.mulm(K).dot(xk)) / (xk.mulm(M).dot(xk));
2167 				rhoRatio = Math.abs(rhoNew-rho)/rhoNew;
2168 				iter++;
2169 				if (iter > maxiter) {
2170 					if (rhoRatio > JSM_TOL) {
2171 						//alert('Eigenvalue solution failed...');
2172 					}
2173 					break;
2174 				}
2175 			} while (rhoRatio > tol)
2176 			eigVals.push(rhoNew);
2177 			eigVecs.push(xk.copy());
2178 			eigVecsMulmM.push(xk.mulm(M));
2179 		}
2180 		return [eigVals,eigVecs];
2181 	}
2182 	if (method == JSM_SUBSPACE) { // subspace iteration
2183 		var n = K.nRows;
2184 		var kk, mm, r, ret, q;
2185 		x = Matrix.Ones(n,nEigModes);
2186 		for (var i=0; i<n; i++) { x.set(i,i,0.); }
2187 		lu = K.luDecomposition()
2188 		for (var i=0; i<50; i++) {
2189 			x = K.solveForRhs(M.x(x),JSM_LU,false,lu);
2190 			kk = x.T().x(K).x(x);
2191 			mm = x.T().x(M).x(x);
2192 			r = eigSolve(kk,mm,nEigModes);
2193 			q = Matrix.Zeros(nEigModes,nEigModes);
2194 			for (var j=0; j<nEigModes; j++) {
2195 				q.setCol(j,r[1][j]);
2196 			}
2197 			x = x.x(q);
2198 		}
2199 		ret = [[],[]];
2200 		for (var i=0; i<nEigModes; i++) {
2201 			ret[0].push(r[0][i]);
2202 			ret[1].push(x.getCol(i));
2203 		}
2204 		return ret;
2205 	}
2206 }
2207 
2208 /** Returns sequence (array) with start, stop, step. Inspired by <a href="www.python.org">Python</a> syntax
2209 * @param {float|int} a start/stop (according to b, see example)
2210 * @param {float|int} [b] stop
2211 * @param {float|int} [c=1] step
2212 * @returns {[floats]} array containing given sequence
2213 * @example r = range(8);     // r = [0,1,2,3,4,5,6,7]
2214 * r = range(2,8);   // r = [2,3,4,5,7]
2215 * r = range(2,8,2); // r = [2,4,6]*/
2216 range = function(a,b,c) {
2217 	var start;
2218 	var step;
2219 	var stop;
2220 	if (b==null && c==null) {
2221 		start = 0;
2222 		stop  = a;
2223 		step  = 1;
2224 	} else if (c==null) {
2225 		start = a;
2226 		stop  = b;
2227 		step  = 1;
2228 	} else {
2229 		start = a;
2230 		stop  = b;
2231 		step  = c;
2232 	}
2233 	var ret = []
2234 	var item = start;
2235 	while (item < stop) {
2236 		ret.push(item);
2237 		item += step;
2238 	}
2239 	return ret;
2240 }
2241 
2242 /**@ignore*/
2243 Array.prototype.indexOf = function(val) {
2244 	for (var i=0; i<this.length; i++) {
2245 		if (this[i] === val) { return i; }
2246 	}
2247 }
2248