mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
Implemented method get, set, resize for Matrix and a lot of other improvements.
This commit is contained in:
parent
895c33cdbe
commit
e64aed8573
556
math.js
556
math.js
@ -439,8 +439,102 @@ var util = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.indexOf, so we define
|
||||
// it here in that case.
|
||||
/**
|
||||
* Recursively resize a multi dimensional array
|
||||
* @param {Array} array Array to be resized
|
||||
* @param {Number[]} size Array with the size of each dimension
|
||||
* @param {Number} dim Current dimension
|
||||
* @param {*} [defaultValue] Value to be filled in in new entries,
|
||||
* 0 by default.
|
||||
* @private
|
||||
*/
|
||||
function _resize (array, size, dim, defaultValue) {
|
||||
if (!(array instanceof Array)) {
|
||||
throw new TypeError('Array expected');
|
||||
}
|
||||
|
||||
var len = array.length,
|
||||
newLen = size[dim];
|
||||
|
||||
if (len != newLen) {
|
||||
if(newLen > array.length) {
|
||||
// enlarge
|
||||
for (var i = array.length; i < newLen; i++) {
|
||||
array[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// shrink
|
||||
array.length = size[dim];
|
||||
}
|
||||
len = array.length;
|
||||
}
|
||||
|
||||
if (dim < size.length - 1) {
|
||||
// recursively validate each child array
|
||||
var dimNext = dim + 1;
|
||||
for (i = 0; i < len; i++) {
|
||||
child = array[i];
|
||||
if (!(child instanceof Array)) {
|
||||
child = [child];
|
||||
array[i] = child;
|
||||
}
|
||||
_resize(child, size, dimNext, defaultValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// last dimension
|
||||
for (i = 0; i < len; i++) {
|
||||
var child = array[i];
|
||||
while (child instanceof Array) {
|
||||
child = child[0];
|
||||
}
|
||||
array[i] = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize a multi dimensional array
|
||||
* @param {Array} array Array to be resized
|
||||
* @param {Number[]} size Array with the size of each dimension
|
||||
* @param {*} [defaultValue] Value to be filled in in new entries,
|
||||
* 0 by default
|
||||
*/
|
||||
util.resize = function resize(array, size, defaultValue) {
|
||||
// TODO: what to do with scalars, when size=[] ?
|
||||
|
||||
// check the type of size
|
||||
if (!(size instanceof Array)) {
|
||||
throw new TypeError('Size must be an array (size is ' + type(size) + ')');
|
||||
}
|
||||
|
||||
// check whether size contains positive integers
|
||||
size.forEach(function (value) {
|
||||
if (!isNumber(value) || !isInteger(value) || value < 0) {
|
||||
throw new TypeError('Invalid size, must contain positive integers ' +
|
||||
'(size: ' + formatArray(size) + ')');
|
||||
}
|
||||
});
|
||||
|
||||
var hasZeros = (size.indexOf(0) != -1);
|
||||
if (hasZeros) {
|
||||
// array where all dimensions are zero
|
||||
size.forEach(function (value) {
|
||||
if (value != 0) {
|
||||
throw new RangeError('Invalid size, all dimensions must be ' +
|
||||
'either zero or non-zero (size: ' + formatArray(size) + ')');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// recursively resize
|
||||
_resize(array, size, 0, defaultValue);
|
||||
};
|
||||
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.indexOf,
|
||||
// so we define it here in that case.
|
||||
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
||||
if(!Array.prototype.indexOf) {
|
||||
Array.prototype.indexOf = function(obj){
|
||||
@ -453,8 +547,8 @@ var util = (function () {
|
||||
};
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.forEach, so we define
|
||||
// it here in that case.
|
||||
// Internet Explorer 8 and older does not support Array.forEach,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
||||
if (!Array.prototype.forEach) {
|
||||
Array.prototype.forEach = function(fn, scope) {
|
||||
@ -464,8 +558,8 @@ var util = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.map, so we define it
|
||||
// here in that case.
|
||||
// Internet Explorer 8 and older does not support Array.map,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
|
||||
// Production steps of ECMA-262, Edition 5, 15.4.4.19
|
||||
// Reference: http://es5.github.com/#x15.4.4.19
|
||||
@ -541,6 +635,34 @@ var util = (function () {
|
||||
};
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.every,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/every
|
||||
if (!Array.prototype.every) {
|
||||
Array.prototype.every = function(fun /*, thisp */) {
|
||||
"use strict";
|
||||
|
||||
if (this == null) {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var t = Object(this);
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun != "function") {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (i in t && !fun.call(thisp, t[i], i, t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
return util;
|
||||
})();
|
||||
|
||||
@ -912,7 +1034,20 @@ Complex.doc = {
|
||||
/**
|
||||
* @constructor Matrix
|
||||
*
|
||||
* TODO: document Matrix
|
||||
* A Matrix is a wrapper around an Array. A matrix can hold a multi dimensional
|
||||
* array. A matrix can be constructed as:
|
||||
* var matrix = new Matrix(data)
|
||||
*
|
||||
* Matrix contains the functions to resize, get and set values, get the size,
|
||||
* clone the matrix and to convert the matrix to a vector, array, or scalar.
|
||||
* The internal Array of the Matrix can be accessed using the method valueOf.
|
||||
*
|
||||
* Example usage:
|
||||
* var matrix = new Matrix([[1, 2], [3, 4]);
|
||||
* matix.size(); // [2, 2]
|
||||
* matrix.resize([3, 2], 5);
|
||||
* matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
|
||||
* matrix.get([1, 0]) // 3
|
||||
*
|
||||
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
|
||||
*/
|
||||
@ -926,9 +1061,17 @@ function Matrix(data) {
|
||||
// clone data from Vector, Matrix, or Range
|
||||
this._data = data.toArray();
|
||||
}
|
||||
else if (data instanceof Array) {
|
||||
// use array as is
|
||||
this._data = data;
|
||||
}
|
||||
else if (data != null) {
|
||||
// a scalar provided
|
||||
this._data = [data];
|
||||
}
|
||||
else {
|
||||
// use data as is
|
||||
this._data = data || null;
|
||||
// nothing provided
|
||||
this._data = [];
|
||||
}
|
||||
|
||||
// verify the size of the array
|
||||
@ -937,9 +1080,148 @@ function Matrix(data) {
|
||||
|
||||
math.Matrix = Matrix;
|
||||
|
||||
// TODO: implement method get
|
||||
/**
|
||||
* Get a value or a set of values from the matrix.
|
||||
* Indexes are zero-based.
|
||||
* @param {Array | Vector | Matrix} index
|
||||
*/
|
||||
Matrix.prototype.get = function (index) {
|
||||
// TODO: support getting a range of values
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Array) {
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var value = this._data;
|
||||
index.forEach(function (i) {
|
||||
if (!isNumber(i) || !isInteger(i) || i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (i > value.length - 1) {
|
||||
throw new RangeError('Index out of range (' + i + ')');
|
||||
}
|
||||
value = value[i];
|
||||
});
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
// TODO: support a single number as index in case the matrix is a vector
|
||||
throw new TypeError('Unsupported type of index ' + type(index));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: implement method set
|
||||
// TODO: implement method resize
|
||||
|
||||
/**
|
||||
* Get a value or a set of values from the matrix.
|
||||
* Indexes are zero-based.
|
||||
* @param {Array | Vector | Matrix} index
|
||||
* @param {*} value
|
||||
*/
|
||||
Matrix.prototype.set = function (index, value) {
|
||||
// TODO: support setting a range of values
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
|
||||
value = value.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Array) {
|
||||
if (value instanceof Array) {
|
||||
throw new Error('Setting a range of values is not yet implemented...');
|
||||
}
|
||||
else {
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var size = this._size.concat([]);
|
||||
var needResize = false;
|
||||
for (var i = 0; i < size.length; i++) {
|
||||
var index_i = index[i];
|
||||
if (!isNumber(index_i) || !isInteger(index_i) || index_i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (index[i] > size[i]) {
|
||||
size[i] = index_i;
|
||||
needResize = true;
|
||||
}
|
||||
}
|
||||
if (needResize) {
|
||||
this.resize(size);
|
||||
}
|
||||
|
||||
var len = size.length;
|
||||
var arr = this._data;
|
||||
index.forEach(function (v, i) {
|
||||
if (i < len - 1) {
|
||||
arr = arr[v];
|
||||
}
|
||||
else {
|
||||
arr[v] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* TODO: cleanup
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var value = this._data;
|
||||
index.forEach(function (i) {
|
||||
if (!isNumber(i) || !isInteger(i) || i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (i > value.length - 1) {
|
||||
throw new RangeError('Index out of range (' + i + ')');
|
||||
}
|
||||
value = value[i];
|
||||
});
|
||||
return value;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// TODO: support a single number as index in case the matrix is a vector
|
||||
throw new TypeError('Unsupported type of index ' + type(index));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize the matrix
|
||||
* @param {Number[]} size
|
||||
* @param {*} [defaultValue] Default value, filled in on new entries.
|
||||
* If not provided, the vector will be filled
|
||||
* with zeros.
|
||||
*/
|
||||
Matrix.prototype.resize = function (size, defaultValue) {
|
||||
util.resize(this._data, size, defaultValue);
|
||||
this._size = clone(size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a clone of the matrix
|
||||
@ -951,7 +1233,6 @@ Matrix.prototype.clone = function () {
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the size of the matrix.
|
||||
* The size of the matrix will be validated too
|
||||
@ -969,7 +1250,7 @@ Matrix.prototype.size = function () {
|
||||
Matrix.prototype.toScalar = function () {
|
||||
var scalar = this._data;
|
||||
while (scalar instanceof Array && scalar.length == 1) {
|
||||
scalar = value[0];
|
||||
scalar = scalar[0];
|
||||
}
|
||||
|
||||
if (scalar instanceof Array) {
|
||||
@ -985,11 +1266,9 @@ Matrix.prototype.toScalar = function () {
|
||||
* @return {boolean} isScalar
|
||||
*/
|
||||
Matrix.prototype.isScalar = function () {
|
||||
var scalar = this._data;
|
||||
while (scalar instanceof Array && scalar.length == 1) {
|
||||
scalar = scalar[0];
|
||||
}
|
||||
return !(scalar instanceof Array);
|
||||
return this._size.every(function (s) {
|
||||
return (s <= 1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -997,26 +1276,37 @@ Matrix.prototype.isScalar = function () {
|
||||
* A matrix is a vector when it has 0 or 1 dimensions, or has multiple
|
||||
* dimensions where maximum one of the dimensions has a size larger than 1.
|
||||
* Returns null if the Matrix is no vector
|
||||
* return {Vector} vector
|
||||
* return {Vector | null} vector
|
||||
*/
|
||||
Matrix.prototype.toVector = function () {
|
||||
/* TODO: implement toVector
|
||||
var count = 0;
|
||||
var dim = undefined;
|
||||
var s = util.size(this._data);
|
||||
s.forEach(function (length, index) {
|
||||
var index = [];
|
||||
this._size.forEach(function (length, i) {
|
||||
if (length > 1) {
|
||||
count++;
|
||||
dim = index;
|
||||
dim = i;
|
||||
}
|
||||
index[i] = 0;
|
||||
});
|
||||
if (count > 1) {
|
||||
|
||||
if (count == 0) {
|
||||
// scalar or empty
|
||||
return new Vector(this.toScalar());
|
||||
}
|
||||
else if (count == 1) {
|
||||
// valid vector
|
||||
var vector = [];
|
||||
for (var i = 0, iMax = this._size[dim]; i < iMax; i++) {
|
||||
index[dim] = i;
|
||||
vector[i] = this.get(index);
|
||||
}
|
||||
return new Vector(vector);
|
||||
}
|
||||
else {
|
||||
// count > 1, this is no vector
|
||||
return null;
|
||||
}
|
||||
|
||||
/// TODO: clone the values
|
||||
*/
|
||||
throw new Error('not yet implemented');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1027,8 +1317,7 @@ Matrix.prototype.toVector = function () {
|
||||
*/
|
||||
Matrix.prototype.isVector = function () {
|
||||
var count = 0;
|
||||
var s = util.size(this._data);
|
||||
s.forEach(function (length) {
|
||||
this._size.forEach(function (length) {
|
||||
if (length > 1) {
|
||||
count++;
|
||||
}
|
||||
@ -1042,11 +1331,7 @@ Matrix.prototype.isVector = function () {
|
||||
* @returns {Array} array
|
||||
*/
|
||||
Matrix.prototype.toArray = function () {
|
||||
var array = clone(this._data);
|
||||
if (!(array instanceof Array)) {
|
||||
array = [array];
|
||||
}
|
||||
return array;
|
||||
return clone(this._data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1959,26 +2244,16 @@ Unit.UNITS = [
|
||||
* array. A vector can be constructed as:
|
||||
* var vector = new Vector(data)
|
||||
*
|
||||
* Vector contains the following functions:
|
||||
* resize(size, defaultValue)
|
||||
* get(index)
|
||||
* get(indexes)
|
||||
* set(index, value)
|
||||
* set(indexes, values)
|
||||
* size()
|
||||
* clone()
|
||||
* isScalar()
|
||||
* toScalar()
|
||||
* isArray()
|
||||
* toArray() // create an Array with the vector data cloned
|
||||
* valueOf() // get the internal data Array of the vector
|
||||
* Vector contains the functions to resize, get and set values, get the size,
|
||||
* clone the vector and to convert the vector to an array or scalar.
|
||||
* The internal Array of the Vector can be accessed using the method valueOf.
|
||||
*
|
||||
* Example usage:
|
||||
* var vector = new Vector([4, 5, 6, 7])
|
||||
* var vector = new Vector([4, 5, 6, 7]);
|
||||
* vector.resize(6, -1);
|
||||
* vector.set(2, 9);
|
||||
* vector.valueOf(); // [4, 5, 9, 7, -1, -1]
|
||||
* vector.get([3,4 ]) // [7, -1]
|
||||
* vector.get([3, 4]) // [7, -1]
|
||||
*
|
||||
* @param {Array | Matrix | Vector | Range} [data] A one dimensional array
|
||||
*/
|
||||
@ -1996,9 +2271,17 @@ function Vector(data) {
|
||||
// clone data from Vector or Range
|
||||
this._data = data.toArray();
|
||||
}
|
||||
else if (data instanceof Array) {
|
||||
// use array as is
|
||||
this._data = data;
|
||||
}
|
||||
else if (data != null) {
|
||||
// a scalar provided
|
||||
this._data = [data];
|
||||
}
|
||||
else {
|
||||
// use data as is
|
||||
this._data = data || null;
|
||||
// nothing provided
|
||||
this._data = [];
|
||||
}
|
||||
|
||||
// verify whether the data is a one dimensional array
|
||||
@ -2033,25 +2316,18 @@ Vector.prototype.resize = function (size, defaultValue) {
|
||||
throw new TypeError('Positive integer expected as size in method resize');
|
||||
}
|
||||
|
||||
if (!(this._data instanceof Array) && size > 1) {
|
||||
// vector currently contains a scalar. change that to an array
|
||||
this._data = [this._data];
|
||||
this.resize(size, defaultValue);
|
||||
if(size > this._data.length) {
|
||||
// enlarge
|
||||
for (var i = this._data.length; i < size; i++) {
|
||||
this._data[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(size > this._data.length) {
|
||||
// enlarge
|
||||
for (var i = this._data.length; i < size; i++) {
|
||||
this._data[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// shrink
|
||||
this._data.length = size;
|
||||
}
|
||||
|
||||
this._size = [this._data.length];
|
||||
// shrink
|
||||
this._data.length = size;
|
||||
}
|
||||
|
||||
this._size = [this._data.length];
|
||||
}
|
||||
};
|
||||
|
||||
@ -2059,13 +2335,24 @@ Vector.prototype.resize = function (size, defaultValue) {
|
||||
* get a value or a subset of the vector. Throws an RangeError when index is
|
||||
* out of range.
|
||||
* Indexes are zero-based.
|
||||
* @param {Number | Number[] | Range} index
|
||||
* @return {* | *[]} value
|
||||
* @param {Number | Array | Matrix | Vector | Range} index
|
||||
* @return {* | Array | Matrix | Vector | Range} value
|
||||
*/
|
||||
Vector.prototype.get = function (index) {
|
||||
var me = this;
|
||||
index = index.valueOf();
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Range || index instanceof Array) {
|
||||
return index.map(function (i) {
|
||||
return me.get(i);
|
||||
@ -2075,58 +2362,61 @@ Vector.prototype.get = function (index) {
|
||||
if (!isNumber(index) || !isInteger(index) || index < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (this._data instanceof Array) {
|
||||
return this._data[index];
|
||||
}
|
||||
else if (index == 0) {
|
||||
return this._data;
|
||||
}
|
||||
else {
|
||||
if (index > this._data.length - 1) {
|
||||
throw new RangeError('Index out of range (' + index + ')');
|
||||
}
|
||||
return this._data[index];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a value or a set of value in the vector.
|
||||
* Set a value or a set of values in the vector.
|
||||
* Indexes are zero-based.
|
||||
* @param {Number | Number[]} index
|
||||
* @param {* | *[]} value
|
||||
* @param {Number | Array | Matrix | Vector | Range} index
|
||||
* @param {* | Array | Matrix | Vector | Range} value
|
||||
*/
|
||||
Vector.prototype.set = function (index, value) {
|
||||
var me = this;
|
||||
index = index.valueOf();
|
||||
|
||||
if (index instanceof Range) {
|
||||
if (index.size() != value.length) {
|
||||
throw new RangeError('Dimension mismatch (' + index.size() + ' != ' +
|
||||
value.length + ')');
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
|
||||
index.forEach(function (v, i) {
|
||||
me._set(v, value[i]);
|
||||
});
|
||||
index = index.toVector();
|
||||
}
|
||||
else if (index instanceof Array) {
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
|
||||
value = value.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Range || index instanceof Array) {
|
||||
if (value instanceof Array) {
|
||||
if (index.length != value.length) {
|
||||
throw new RangeError('Dimension mismatch (' + index.length+ ' != ' +
|
||||
value.length + ')');
|
||||
if (size(index) != value.length) {
|
||||
throw new RangeError('Dimension mismatch ' +
|
||||
'(' + size(index) + ' != ' + value.length + ')');
|
||||
}
|
||||
|
||||
index.forEach(function (v, i) {
|
||||
me._set(v, value[i]);
|
||||
me._set(v, value[i]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.set(index, [value]);
|
||||
index.forEach(function (v) {
|
||||
me._set(v, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// index is a scalar
|
||||
if (value instanceof Array) {
|
||||
// try as two arrays
|
||||
this.set([index], value);
|
||||
}
|
||||
else {
|
||||
// set single value
|
||||
this._set(index, value);
|
||||
}
|
||||
}
|
||||
@ -2139,9 +2429,6 @@ Vector.prototype.set = function (index, value) {
|
||||
* @private
|
||||
*/
|
||||
Vector.prototype._set = function (index, value) {
|
||||
if (!(this._data instanceof Array)) {
|
||||
this._data = [this._data];
|
||||
}
|
||||
if (index > this._data.length) {
|
||||
this.resize(index);
|
||||
}
|
||||
@ -2173,16 +2460,11 @@ Vector.prototype.size = function () {
|
||||
* @return {* | null} scalar
|
||||
*/
|
||||
Vector.prototype.toScalar = function () {
|
||||
var value = this._data;
|
||||
while (value instanceof Array && value.length == 1) {
|
||||
value = value[0];
|
||||
}
|
||||
|
||||
if (value instanceof Array) {
|
||||
return null;
|
||||
if (this._data.length == 1) {
|
||||
return this._data[0];
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -2191,11 +2473,7 @@ Vector.prototype.toScalar = function () {
|
||||
* @return {boolean} isScalar
|
||||
*/
|
||||
Vector.prototype.isScalar = function () {
|
||||
var value = this._data;
|
||||
while (value instanceof Array && value.length == 1) {
|
||||
value = value[0];
|
||||
}
|
||||
return !(value instanceof Array);
|
||||
return (this._data.length <= 1);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2204,11 +2482,7 @@ Vector.prototype.isScalar = function () {
|
||||
* @returns {Array} array
|
||||
*/
|
||||
Vector.prototype.toArray = function () {
|
||||
var array = clone(this._data);
|
||||
if (!(array instanceof Array)) {
|
||||
array = [array];
|
||||
}
|
||||
return array;
|
||||
return clone(this._data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -4556,49 +4830,6 @@ eye.doc = {
|
||||
'diag', 'ones', 'range', 'size', 'transpose', 'zeros'
|
||||
]
|
||||
};
|
||||
/**
|
||||
* Create a range. range(start[, step], end) or start:end
|
||||
* @param {Number} start
|
||||
* @param {Number} [step]
|
||||
* @param {Number} end
|
||||
* @return {Number[]} range
|
||||
*/
|
||||
function range (start, step, end) {
|
||||
if (arguments.length != 1 && arguments.length != 2) {
|
||||
throw newArgumentsError('range', arguments.length, 1);
|
||||
}
|
||||
|
||||
var r = new Range(start, end, step);
|
||||
return r.toArray();
|
||||
}
|
||||
|
||||
math.range = range;
|
||||
|
||||
/**
|
||||
* Function documentation
|
||||
*/
|
||||
range.doc = {
|
||||
'name': 'range',
|
||||
'category': 'Matrix',
|
||||
'syntax': [
|
||||
'start : end',
|
||||
'start : step : end',
|
||||
'range(start, end)',
|
||||
'range(start, step, end)'
|
||||
],
|
||||
'description': 'Create a range.',
|
||||
'examples': [
|
||||
'1:10',
|
||||
'0:10:100',
|
||||
'0:0.2:1',
|
||||
'range(20, -1, 10)',
|
||||
'matrix = [1, 2, 3; 4, 5, 6; 7, 8, 9]',
|
||||
'matrix(2:3, 1:2)'
|
||||
],
|
||||
'seealso': [
|
||||
'diag', 'eye', 'ones', 'size', 'transpose', 'zeros'
|
||||
]
|
||||
};
|
||||
/**
|
||||
* Calculate the size of a vector, matrix, or scalar. size(x)
|
||||
* @param {Number | Complex | Array} x
|
||||
@ -5615,11 +5846,16 @@ function clone(x) {
|
||||
throw newArgumentsError('clone', arguments.length, 1);
|
||||
}
|
||||
|
||||
if (x == null) {
|
||||
// null or undefined
|
||||
return x;
|
||||
}
|
||||
|
||||
if (typeof(x.clone) === 'function') {
|
||||
return x.clone();
|
||||
}
|
||||
|
||||
if (isNumber(x) || isString(x) || x === null) {
|
||||
if (isNumber(x) || isString(x)) {
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
6
math.min.js
vendored
6
math.min.js
vendored
File diff suppressed because one or more lines are too long
@ -8,11 +8,16 @@ function clone(x) {
|
||||
throw newArgumentsError('clone', arguments.length, 1);
|
||||
}
|
||||
|
||||
if (x == null) {
|
||||
// null or undefined
|
||||
return x;
|
||||
}
|
||||
|
||||
if (typeof(x.clone) === 'function') {
|
||||
return x.clone();
|
||||
}
|
||||
|
||||
if (isNumber(x) || isString(x) || x === null) {
|
||||
if (isNumber(x) || isString(x)) {
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,20 @@
|
||||
/**
|
||||
* @constructor Matrix
|
||||
*
|
||||
* TODO: document Matrix
|
||||
* A Matrix is a wrapper around an Array. A matrix can hold a multi dimensional
|
||||
* array. A matrix can be constructed as:
|
||||
* var matrix = new Matrix(data)
|
||||
*
|
||||
* Matrix contains the functions to resize, get and set values, get the size,
|
||||
* clone the matrix and to convert the matrix to a vector, array, or scalar.
|
||||
* The internal Array of the Matrix can be accessed using the method valueOf.
|
||||
*
|
||||
* Example usage:
|
||||
* var matrix = new Matrix([[1, 2], [3, 4]);
|
||||
* matix.size(); // [2, 2]
|
||||
* matrix.resize([3, 2], 5);
|
||||
* matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
|
||||
* matrix.get([1, 0]) // 3
|
||||
*
|
||||
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
|
||||
*/
|
||||
@ -15,9 +28,17 @@ function Matrix(data) {
|
||||
// clone data from Vector, Matrix, or Range
|
||||
this._data = data.toArray();
|
||||
}
|
||||
else if (data instanceof Array) {
|
||||
// use array as is
|
||||
this._data = data;
|
||||
}
|
||||
else if (data != null) {
|
||||
// a scalar provided
|
||||
this._data = [data];
|
||||
}
|
||||
else {
|
||||
// use data as is
|
||||
this._data = data || null;
|
||||
// nothing provided
|
||||
this._data = [];
|
||||
}
|
||||
|
||||
// verify the size of the array
|
||||
@ -26,9 +47,148 @@ function Matrix(data) {
|
||||
|
||||
math.Matrix = Matrix;
|
||||
|
||||
// TODO: implement method get
|
||||
/**
|
||||
* Get a value or a set of values from the matrix.
|
||||
* Indexes are zero-based.
|
||||
* @param {Array | Vector | Matrix} index
|
||||
*/
|
||||
Matrix.prototype.get = function (index) {
|
||||
// TODO: support getting a range of values
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Array) {
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var value = this._data;
|
||||
index.forEach(function (i) {
|
||||
if (!isNumber(i) || !isInteger(i) || i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (i > value.length - 1) {
|
||||
throw new RangeError('Index out of range (' + i + ')');
|
||||
}
|
||||
value = value[i];
|
||||
});
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
// TODO: support a single number as index in case the matrix is a vector
|
||||
throw new TypeError('Unsupported type of index ' + type(index));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: implement method set
|
||||
// TODO: implement method resize
|
||||
|
||||
/**
|
||||
* Get a value or a set of values from the matrix.
|
||||
* Indexes are zero-based.
|
||||
* @param {Array | Vector | Matrix} index
|
||||
* @param {*} value
|
||||
*/
|
||||
Matrix.prototype.set = function (index, value) {
|
||||
// TODO: support setting a range of values
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
|
||||
value = value.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Array) {
|
||||
if (value instanceof Array) {
|
||||
throw new Error('Setting a range of values is not yet implemented...');
|
||||
}
|
||||
else {
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var size = this._size.concat([]);
|
||||
var needResize = false;
|
||||
for (var i = 0; i < size.length; i++) {
|
||||
var index_i = index[i];
|
||||
if (!isNumber(index_i) || !isInteger(index_i) || index_i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (index[i] > size[i]) {
|
||||
size[i] = index_i;
|
||||
needResize = true;
|
||||
}
|
||||
}
|
||||
if (needResize) {
|
||||
this.resize(size);
|
||||
}
|
||||
|
||||
var len = size.length;
|
||||
var arr = this._data;
|
||||
index.forEach(function (v, i) {
|
||||
if (i < len - 1) {
|
||||
arr = arr[v];
|
||||
}
|
||||
else {
|
||||
arr[v] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* TODO: cleanup
|
||||
if (index.length != this._size.length) {
|
||||
throw new RangeError('Number of dimensions do not match ' +
|
||||
'(' + index.length + ' != ' + this._size.length + ')');
|
||||
}
|
||||
|
||||
var value = this._data;
|
||||
index.forEach(function (i) {
|
||||
if (!isNumber(i) || !isInteger(i) || i < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (i > value.length - 1) {
|
||||
throw new RangeError('Index out of range (' + i + ')');
|
||||
}
|
||||
value = value[i];
|
||||
});
|
||||
return value;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// TODO: support a single number as index in case the matrix is a vector
|
||||
throw new TypeError('Unsupported type of index ' + type(index));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize the matrix
|
||||
* @param {Number[]} size
|
||||
* @param {*} [defaultValue] Default value, filled in on new entries.
|
||||
* If not provided, the vector will be filled
|
||||
* with zeros.
|
||||
*/
|
||||
Matrix.prototype.resize = function (size, defaultValue) {
|
||||
util.resize(this._data, size, defaultValue);
|
||||
this._size = clone(size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a clone of the matrix
|
||||
@ -40,7 +200,6 @@ Matrix.prototype.clone = function () {
|
||||
return matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the size of the matrix.
|
||||
* The size of the matrix will be validated too
|
||||
@ -58,7 +217,7 @@ Matrix.prototype.size = function () {
|
||||
Matrix.prototype.toScalar = function () {
|
||||
var scalar = this._data;
|
||||
while (scalar instanceof Array && scalar.length == 1) {
|
||||
scalar = value[0];
|
||||
scalar = scalar[0];
|
||||
}
|
||||
|
||||
if (scalar instanceof Array) {
|
||||
@ -74,11 +233,9 @@ Matrix.prototype.toScalar = function () {
|
||||
* @return {boolean} isScalar
|
||||
*/
|
||||
Matrix.prototype.isScalar = function () {
|
||||
var scalar = this._data;
|
||||
while (scalar instanceof Array && scalar.length == 1) {
|
||||
scalar = scalar[0];
|
||||
}
|
||||
return !(scalar instanceof Array);
|
||||
return this._size.every(function (s) {
|
||||
return (s <= 1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -86,26 +243,37 @@ Matrix.prototype.isScalar = function () {
|
||||
* A matrix is a vector when it has 0 or 1 dimensions, or has multiple
|
||||
* dimensions where maximum one of the dimensions has a size larger than 1.
|
||||
* Returns null if the Matrix is no vector
|
||||
* return {Vector} vector
|
||||
* return {Vector | null} vector
|
||||
*/
|
||||
Matrix.prototype.toVector = function () {
|
||||
/* TODO: implement toVector
|
||||
var count = 0;
|
||||
var dim = undefined;
|
||||
var s = util.size(this._data);
|
||||
s.forEach(function (length, index) {
|
||||
var index = [];
|
||||
this._size.forEach(function (length, i) {
|
||||
if (length > 1) {
|
||||
count++;
|
||||
dim = index;
|
||||
dim = i;
|
||||
}
|
||||
index[i] = 0;
|
||||
});
|
||||
if (count > 1) {
|
||||
|
||||
if (count == 0) {
|
||||
// scalar or empty
|
||||
return new Vector(this.toScalar());
|
||||
}
|
||||
else if (count == 1) {
|
||||
// valid vector
|
||||
var vector = [];
|
||||
for (var i = 0, iMax = this._size[dim]; i < iMax; i++) {
|
||||
index[dim] = i;
|
||||
vector[i] = this.get(index);
|
||||
}
|
||||
return new Vector(vector);
|
||||
}
|
||||
else {
|
||||
// count > 1, this is no vector
|
||||
return null;
|
||||
}
|
||||
|
||||
/// TODO: clone the values
|
||||
*/
|
||||
throw new Error('not yet implemented');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -116,8 +284,7 @@ Matrix.prototype.toVector = function () {
|
||||
*/
|
||||
Matrix.prototype.isVector = function () {
|
||||
var count = 0;
|
||||
var s = util.size(this._data);
|
||||
s.forEach(function (length) {
|
||||
this._size.forEach(function (length) {
|
||||
if (length > 1) {
|
||||
count++;
|
||||
}
|
||||
@ -131,11 +298,7 @@ Matrix.prototype.isVector = function () {
|
||||
* @returns {Array} array
|
||||
*/
|
||||
Matrix.prototype.toArray = function () {
|
||||
var array = clone(this._data);
|
||||
if (!(array instanceof Array)) {
|
||||
array = [array];
|
||||
}
|
||||
return array;
|
||||
return clone(this._data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -4,26 +4,16 @@
|
||||
* array. A vector can be constructed as:
|
||||
* var vector = new Vector(data)
|
||||
*
|
||||
* Vector contains the following functions:
|
||||
* resize(size, defaultValue)
|
||||
* get(index)
|
||||
* get(indexes)
|
||||
* set(index, value)
|
||||
* set(indexes, values)
|
||||
* size()
|
||||
* clone()
|
||||
* isScalar()
|
||||
* toScalar()
|
||||
* isArray()
|
||||
* toArray() // create an Array with the vector data cloned
|
||||
* valueOf() // get the internal data Array of the vector
|
||||
* Vector contains the functions to resize, get and set values, get the size,
|
||||
* clone the vector and to convert the vector to an array or scalar.
|
||||
* The internal Array of the Vector can be accessed using the method valueOf.
|
||||
*
|
||||
* Example usage:
|
||||
* var vector = new Vector([4, 5, 6, 7])
|
||||
* var vector = new Vector([4, 5, 6, 7]);
|
||||
* vector.resize(6, -1);
|
||||
* vector.set(2, 9);
|
||||
* vector.valueOf(); // [4, 5, 9, 7, -1, -1]
|
||||
* vector.get([3,4 ]) // [7, -1]
|
||||
* vector.get([3, 4]) // [7, -1]
|
||||
*
|
||||
* @param {Array | Matrix | Vector | Range} [data] A one dimensional array
|
||||
*/
|
||||
@ -41,9 +31,17 @@ function Vector(data) {
|
||||
// clone data from Vector or Range
|
||||
this._data = data.toArray();
|
||||
}
|
||||
else if (data instanceof Array) {
|
||||
// use array as is
|
||||
this._data = data;
|
||||
}
|
||||
else if (data != null) {
|
||||
// a scalar provided
|
||||
this._data = [data];
|
||||
}
|
||||
else {
|
||||
// use data as is
|
||||
this._data = data || null;
|
||||
// nothing provided
|
||||
this._data = [];
|
||||
}
|
||||
|
||||
// verify whether the data is a one dimensional array
|
||||
@ -78,25 +76,18 @@ Vector.prototype.resize = function (size, defaultValue) {
|
||||
throw new TypeError('Positive integer expected as size in method resize');
|
||||
}
|
||||
|
||||
if (!(this._data instanceof Array) && size > 1) {
|
||||
// vector currently contains a scalar. change that to an array
|
||||
this._data = [this._data];
|
||||
this.resize(size, defaultValue);
|
||||
if(size > this._data.length) {
|
||||
// enlarge
|
||||
for (var i = this._data.length; i < size; i++) {
|
||||
this._data[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(size > this._data.length) {
|
||||
// enlarge
|
||||
for (var i = this._data.length; i < size; i++) {
|
||||
this._data[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// shrink
|
||||
this._data.length = size;
|
||||
}
|
||||
|
||||
this._size = [this._data.length];
|
||||
// shrink
|
||||
this._data.length = size;
|
||||
}
|
||||
|
||||
this._size = [this._data.length];
|
||||
}
|
||||
};
|
||||
|
||||
@ -104,13 +95,24 @@ Vector.prototype.resize = function (size, defaultValue) {
|
||||
* get a value or a subset of the vector. Throws an RangeError when index is
|
||||
* out of range.
|
||||
* Indexes are zero-based.
|
||||
* @param {Number | Number[] | Range} index
|
||||
* @return {* | *[]} value
|
||||
* @param {Number | Array | Matrix | Vector | Range} index
|
||||
* @return {* | Array | Matrix | Vector | Range} value
|
||||
*/
|
||||
Vector.prototype.get = function (index) {
|
||||
var me = this;
|
||||
index = index.valueOf();
|
||||
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
index = index.toVector();
|
||||
}
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Range || index instanceof Array) {
|
||||
return index.map(function (i) {
|
||||
return me.get(i);
|
||||
@ -120,58 +122,61 @@ Vector.prototype.get = function (index) {
|
||||
if (!isNumber(index) || !isInteger(index) || index < 0) {
|
||||
throw new TypeError('Positive integer expected as index in method get');
|
||||
}
|
||||
if (this._data instanceof Array) {
|
||||
return this._data[index];
|
||||
}
|
||||
else if (index == 0) {
|
||||
return this._data;
|
||||
}
|
||||
else {
|
||||
if (index > this._data.length - 1) {
|
||||
throw new RangeError('Index out of range (' + index + ')');
|
||||
}
|
||||
return this._data[index];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a value or a set of value in the vector.
|
||||
* Set a value or a set of values in the vector.
|
||||
* Indexes are zero-based.
|
||||
* @param {Number | Number[]} index
|
||||
* @param {* | *[]} value
|
||||
* @param {Number | Array | Matrix | Vector | Range} index
|
||||
* @param {* | Array | Matrix | Vector | Range} value
|
||||
*/
|
||||
Vector.prototype.set = function (index, value) {
|
||||
var me = this;
|
||||
index = index.valueOf();
|
||||
|
||||
if (index instanceof Range) {
|
||||
if (index.size() != value.length) {
|
||||
throw new RangeError('Dimension mismatch (' + index.size() + ' != ' +
|
||||
value.length + ')');
|
||||
if (index instanceof Matrix) {
|
||||
if (!index.isVector()) {
|
||||
throw new RangeError('Index must be a vector ' +
|
||||
'(size: ' + format(index.size()) + ')');
|
||||
}
|
||||
|
||||
index.forEach(function (v, i) {
|
||||
me._set(v, value[i]);
|
||||
});
|
||||
index = index.toVector();
|
||||
}
|
||||
else if (index instanceof Array) {
|
||||
if (index instanceof Vector) {
|
||||
index = index.valueOf();
|
||||
}
|
||||
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
|
||||
value = value.valueOf();
|
||||
}
|
||||
|
||||
if (index instanceof Range || index instanceof Array) {
|
||||
if (value instanceof Array) {
|
||||
if (index.length != value.length) {
|
||||
throw new RangeError('Dimension mismatch (' + index.length+ ' != ' +
|
||||
value.length + ')');
|
||||
if (size(index) != value.length) {
|
||||
throw new RangeError('Dimension mismatch ' +
|
||||
'(' + size(index) + ' != ' + value.length + ')');
|
||||
}
|
||||
|
||||
index.forEach(function (v, i) {
|
||||
me._set(v, value[i]);
|
||||
me._set(v, value[i]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.set(index, [value]);
|
||||
index.forEach(function (v) {
|
||||
me._set(v, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// index is a scalar
|
||||
if (value instanceof Array) {
|
||||
// try as two arrays
|
||||
this.set([index], value);
|
||||
}
|
||||
else {
|
||||
// set single value
|
||||
this._set(index, value);
|
||||
}
|
||||
}
|
||||
@ -184,9 +189,6 @@ Vector.prototype.set = function (index, value) {
|
||||
* @private
|
||||
*/
|
||||
Vector.prototype._set = function (index, value) {
|
||||
if (!(this._data instanceof Array)) {
|
||||
this._data = [this._data];
|
||||
}
|
||||
if (index > this._data.length) {
|
||||
this.resize(index);
|
||||
}
|
||||
@ -218,16 +220,11 @@ Vector.prototype.size = function () {
|
||||
* @return {* | null} scalar
|
||||
*/
|
||||
Vector.prototype.toScalar = function () {
|
||||
var value = this._data;
|
||||
while (value instanceof Array && value.length == 1) {
|
||||
value = value[0];
|
||||
}
|
||||
|
||||
if (value instanceof Array) {
|
||||
return null;
|
||||
if (this._data.length == 1) {
|
||||
return this._data[0];
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,11 +233,7 @@ Vector.prototype.toScalar = function () {
|
||||
* @return {boolean} isScalar
|
||||
*/
|
||||
Vector.prototype.isScalar = function () {
|
||||
var value = this._data;
|
||||
while (value instanceof Array && value.length == 1) {
|
||||
value = value[0];
|
||||
}
|
||||
return !(value instanceof Array);
|
||||
return (this._data.length <= 1);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -249,11 +242,7 @@ Vector.prototype.isScalar = function () {
|
||||
* @returns {Array} array
|
||||
*/
|
||||
Vector.prototype.toArray = function () {
|
||||
var array = clone(this._data);
|
||||
if (!(array instanceof Array)) {
|
||||
array = [array];
|
||||
}
|
||||
return array;
|
||||
return clone(this._data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
134
src/util.js
134
src/util.js
@ -372,8 +372,102 @@ var util = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.indexOf, so we define
|
||||
// it here in that case.
|
||||
/**
|
||||
* Recursively resize a multi dimensional array
|
||||
* @param {Array} array Array to be resized
|
||||
* @param {Number[]} size Array with the size of each dimension
|
||||
* @param {Number} dim Current dimension
|
||||
* @param {*} [defaultValue] Value to be filled in in new entries,
|
||||
* 0 by default.
|
||||
* @private
|
||||
*/
|
||||
function _resize (array, size, dim, defaultValue) {
|
||||
if (!(array instanceof Array)) {
|
||||
throw new TypeError('Array expected');
|
||||
}
|
||||
|
||||
var len = array.length,
|
||||
newLen = size[dim];
|
||||
|
||||
if (len != newLen) {
|
||||
if(newLen > array.length) {
|
||||
// enlarge
|
||||
for (var i = array.length; i < newLen; i++) {
|
||||
array[i] = defaultValue ? clone(defaultValue) : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// shrink
|
||||
array.length = size[dim];
|
||||
}
|
||||
len = array.length;
|
||||
}
|
||||
|
||||
if (dim < size.length - 1) {
|
||||
// recursively validate each child array
|
||||
var dimNext = dim + 1;
|
||||
for (i = 0; i < len; i++) {
|
||||
child = array[i];
|
||||
if (!(child instanceof Array)) {
|
||||
child = [child];
|
||||
array[i] = child;
|
||||
}
|
||||
_resize(child, size, dimNext, defaultValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// last dimension
|
||||
for (i = 0; i < len; i++) {
|
||||
var child = array[i];
|
||||
while (child instanceof Array) {
|
||||
child = child[0];
|
||||
}
|
||||
array[i] = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize a multi dimensional array
|
||||
* @param {Array} array Array to be resized
|
||||
* @param {Number[]} size Array with the size of each dimension
|
||||
* @param {*} [defaultValue] Value to be filled in in new entries,
|
||||
* 0 by default
|
||||
*/
|
||||
util.resize = function resize(array, size, defaultValue) {
|
||||
// TODO: what to do with scalars, when size=[] ?
|
||||
|
||||
// check the type of size
|
||||
if (!(size instanceof Array)) {
|
||||
throw new TypeError('Size must be an array (size is ' + type(size) + ')');
|
||||
}
|
||||
|
||||
// check whether size contains positive integers
|
||||
size.forEach(function (value) {
|
||||
if (!isNumber(value) || !isInteger(value) || value < 0) {
|
||||
throw new TypeError('Invalid size, must contain positive integers ' +
|
||||
'(size: ' + formatArray(size) + ')');
|
||||
}
|
||||
});
|
||||
|
||||
var hasZeros = (size.indexOf(0) != -1);
|
||||
if (hasZeros) {
|
||||
// array where all dimensions are zero
|
||||
size.forEach(function (value) {
|
||||
if (value != 0) {
|
||||
throw new RangeError('Invalid size, all dimensions must be ' +
|
||||
'either zero or non-zero (size: ' + formatArray(size) + ')');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// recursively resize
|
||||
_resize(array, size, 0, defaultValue);
|
||||
};
|
||||
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.indexOf,
|
||||
// so we define it here in that case.
|
||||
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
||||
if(!Array.prototype.indexOf) {
|
||||
Array.prototype.indexOf = function(obj){
|
||||
@ -386,8 +480,8 @@ var util = (function () {
|
||||
};
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.forEach, so we define
|
||||
// it here in that case.
|
||||
// Internet Explorer 8 and older does not support Array.forEach,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
||||
if (!Array.prototype.forEach) {
|
||||
Array.prototype.forEach = function(fn, scope) {
|
||||
@ -397,8 +491,8 @@ var util = (function () {
|
||||
}
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.map, so we define it
|
||||
// here in that case.
|
||||
// Internet Explorer 8 and older does not support Array.map,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
|
||||
// Production steps of ECMA-262, Edition 5, 15.4.4.19
|
||||
// Reference: http://es5.github.com/#x15.4.4.19
|
||||
@ -474,5 +568,33 @@ var util = (function () {
|
||||
};
|
||||
}
|
||||
|
||||
// Internet Explorer 8 and older does not support Array.every,
|
||||
// so we define it here in that case.
|
||||
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/every
|
||||
if (!Array.prototype.every) {
|
||||
Array.prototype.every = function(fun /*, thisp */) {
|
||||
"use strict";
|
||||
|
||||
if (this == null) {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var t = Object(this);
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun != "function") {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (i in t && !fun.call(thisp, t[i], i, t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
return util;
|
||||
})();
|
||||
|
||||
@ -24,8 +24,8 @@ assert.deepEqual(math.size('hello'), [5]);
|
||||
assert.deepEqual(math.size(''), [0]);
|
||||
assert.deepEqual(math.size(new Complex(2,3)), []);
|
||||
assert.deepEqual(math.size(null), []);
|
||||
assert.deepEqual(math.size(new Vector()), []);
|
||||
assert.deepEqual(math.size(new Matrix()), []);
|
||||
assert.deepEqual(math.size(new Vector()), [0]);
|
||||
assert.deepEqual(math.size(new Matrix()), [0]);
|
||||
assert.deepEqual(math.size(new Range(2,5)), [4]);
|
||||
// TODO: test whether math.size throws an error in case of invalid data or size
|
||||
|
||||
|
||||
@ -11,6 +11,9 @@
|
||||
</p>
|
||||
<script>
|
||||
var Complex = math.Complex;
|
||||
var Matrix = math.Matrix;
|
||||
var Vector = math.Vector;
|
||||
var Range = math.Range;
|
||||
var Unit = math.Unit;
|
||||
|
||||
var complex1 = new Complex(3, -4);
|
||||
|
||||
@ -4,6 +4,107 @@ var assert = require('assert');
|
||||
var math = require('../../math.js'),
|
||||
Complex = math.Complex,
|
||||
Matrix = math.Matrix,
|
||||
Vector = math.Vector,
|
||||
Range = math.Range,
|
||||
Unit = math.Unit;
|
||||
|
||||
var m = new Matrix();
|
||||
assert.equal(m.isScalar(), true);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [0]);
|
||||
assert.deepEqual(m.toScalar(), null);
|
||||
assert.throws(function () { m.get([0]); });
|
||||
|
||||
m = new Matrix([[23]]);
|
||||
assert.equal(m.isScalar(), true);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [1,1]);
|
||||
assert.deepEqual(m.toScalar(), 23);
|
||||
assert.deepEqual(m.get([0,0]), 23);
|
||||
|
||||
m = new Matrix([[1,2,3],[4,5,6]]);
|
||||
assert.equal(m.isScalar(), false);
|
||||
assert.equal(m.isVector(), false);
|
||||
assert.deepEqual(m.size(), [2,3]);
|
||||
assert.equal(m.get([1,2]), 6);
|
||||
assert.equal(m.get([0,1]), 2);
|
||||
assert.throws(function () { m.get([1,2, 3]); });
|
||||
assert.throws(function () { m.get([3,0]); });
|
||||
assert.throws(function () { m.get([1]); });
|
||||
|
||||
m = new Matrix([1,2,3]);
|
||||
assert.equal(m.isScalar(), false);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [3]);
|
||||
assert.deepEqual(m.toVector().valueOf(), [1,2,3]);
|
||||
|
||||
m = new Matrix([[1],[2],[3]]);
|
||||
assert.equal(m.isScalar(), false);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [3,1]);
|
||||
assert.deepEqual(m.toVector().valueOf(), [1,2,3]);
|
||||
|
||||
m = new Matrix([[[1],[2],[3]]]);
|
||||
assert.equal(m.isScalar(), false);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [1,3,1]);
|
||||
assert.deepEqual(m.toVector().valueOf(), [1,2,3]);
|
||||
|
||||
m = new Matrix([[[3]]]);
|
||||
assert.equal(m.isScalar(), true);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [1,1,1]);
|
||||
assert.deepEqual(m.toVector().valueOf(), [3]);
|
||||
|
||||
m = new Matrix([[]]);
|
||||
assert.equal(m.isScalar(), true);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [0,0]);
|
||||
assert.deepEqual(m.toVector().valueOf(), []);
|
||||
|
||||
m = new Matrix();
|
||||
assert.equal(m.isScalar(), true);
|
||||
assert.equal(m.isVector(), true);
|
||||
assert.deepEqual(m.size(), [0]);
|
||||
assert.deepEqual(m.toVector().valueOf(), []);
|
||||
|
||||
// test resizing
|
||||
m = new Matrix([[1,2,3],[4,5,6]]);
|
||||
assert.deepEqual(m.size(), [2,3]);
|
||||
m.resize([2,4]);
|
||||
assert.deepEqual(m.size(), [2,4]);
|
||||
assert.deepEqual(m.valueOf(), [[1,2,3,0],[4,5,6,0]]);
|
||||
m.resize([1,2]);
|
||||
assert.deepEqual(m.size(), [1,2]);
|
||||
assert.deepEqual(m.valueOf(), [[1,2]]);
|
||||
m.resize([1,2,2], 8);
|
||||
assert.deepEqual(m.size(), [1,2,2]);
|
||||
assert.deepEqual(m.valueOf(), [[[1,8],[2,8]]]);
|
||||
m.resize([2,3], 9);
|
||||
assert.deepEqual(m.size(), [2,3]);
|
||||
assert.deepEqual(m.valueOf(), [[1, 2, 9], [9, 9, 9]]);
|
||||
m = new Matrix();
|
||||
assert.deepEqual(m.size(), [0]);
|
||||
m.resize([3,3,3], 6);
|
||||
assert.deepEqual(m.size(), [3,3,3]);
|
||||
assert.deepEqual(m.valueOf(), [
|
||||
[[6,6,6],[6,6,6],[6,6,6]],
|
||||
[[6,6,6],[6,6,6],[6,6,6]],
|
||||
[[6,6,6],[6,6,6],[6,6,6]]
|
||||
]);
|
||||
m.set([2,2,1], 3);
|
||||
assert.deepEqual(m.valueOf(), [
|
||||
[[6,6,6],[6,6,6],[6,6,6]],
|
||||
[[6,6,6],[6,6,6],[6,6,6]],
|
||||
[[6,6,6],[6,6,6],[6,3,6]]
|
||||
]);
|
||||
m.resize([2,2]);
|
||||
assert.deepEqual(m.size(), [2,2]);
|
||||
assert.deepEqual(m.valueOf(), [[6,6],[6,6]]);
|
||||
m.set([1,0], 3);
|
||||
assert.deepEqual(m.valueOf(), [[6,6],[3,6]]);
|
||||
m.resize([0]);
|
||||
assert.deepEqual(m.size(), [0]);
|
||||
assert.deepEqual(m.valueOf(), []);
|
||||
|
||||
// TODO: extensively test Matrix
|
||||
|
||||
@ -32,5 +32,9 @@ assert.deepEqual(v.valueOf(), [100]);
|
||||
var s = v.toScalar();
|
||||
assert.deepEqual(s, 100);
|
||||
|
||||
v = new Vector();
|
||||
assert.deepEqual(v.size(), [0]);
|
||||
v.set(new math.Range(2,2,10), 7);
|
||||
assert.deepEqual(v.valueOf(), [0,0,7,0,7,0,7,0,7,0,7]);
|
||||
|
||||
// TODO: extensively test Vector
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user