Removed Vector, as it is redundant with Matrix and only adds complexity.

This commit is contained in:
josdejong 2013-03-28 21:05:05 +01:00
parent 0309f62e3f
commit b07920fac8
17 changed files with 213 additions and 814 deletions

View File

@ -6,7 +6,7 @@ https://github.com/josdejong/mathjs
*Note: version 0.5 is incompatible with previous versions.*
- Implemented data types Vector, Matrix, and Range.
- Implemented data types Matrix and Range.
- Implemented methods clone, size, identity.
- Changed: moved all type constructors in the namespace under math.type,
created construction methods for easy object creation. For example, a complex

View File

@ -10,7 +10,7 @@ Powerful and easy to use.
## Features
- Supports numbers, complex numbers, units, strings, and matrices.
- Supports numbers, complex numbers, units, strings, arrays, and matrices.
- Contains a large set of built-in functions and constants.
- Contains a flexible expression parser.
- Compatible with JavaScripts built-in Math library.

482
math.js
View File

@ -170,7 +170,7 @@ var util = (function () {
* fn(n)
* fn(m, n, p, ...)
* fn([m, n, p, ...])
* @param {...Number | Array | Matrix | Vector} args
* @param {...Number | Array | Matrix} args
* @returns {Array} array
*/
util.argsToArray = function argsToArray(args) {
@ -186,7 +186,7 @@ var util = (function () {
if (array instanceof Matrix) {
array = array.toVector();
}
if (array instanceof Vector || array instanceof Range) {
if (array instanceof Range) {
array = array.valueOf();
}
if (!(array instanceof Array)) {
@ -547,7 +547,7 @@ var util = (function () {
// check the type of size
if (!(size instanceof Array)) {
throw new TypeError('Size must be an array (size is ' + type(size) + ')');
throw new TypeError('Size must be an array (size is ' + math.typeof(size) + ')');
}
// check whether size contains positive integers
@ -1054,7 +1054,7 @@ Complex.doc = {
* matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
* matrix.get([1, 0]) // 3
*
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
* @param {Array | Matrix | Range} [data] A multi dimensional array
*/
function Matrix(data) {
if (this.constructor != Matrix) {
@ -1062,8 +1062,8 @@ function Matrix(data) {
'Matrix constructor must be called with the new operator');
}
if (data instanceof Matrix || data instanceof Vector || data instanceof Range) {
// clone data from Vector, Matrix, or Range
if (data instanceof Matrix || data instanceof Range) {
// clone data from a Matrix or Range
this._data = data.toArray();
}
else if (data instanceof Array) {
@ -1088,7 +1088,7 @@ math.type.Matrix = Matrix;
/**
* Get a value or a set of values from the matrix.
* Indexes are zero-based.
* @param {Array | Vector | Matrix} index
* @param {Array | Matrix} index
*/
Matrix.prototype.get = function (index) {
// TODO: support syntax Matrix.get(m,n,p, ...)
@ -1101,8 +1101,8 @@ Matrix.prototype.get = function (index) {
}
index = index.toVector();
}
if (index instanceof Vector) {
index = index.valueOf();
if (index instanceof Range) {
index = index.toArray();
}
if (index instanceof Array) {
@ -1125,14 +1125,14 @@ Matrix.prototype.get = function (index) {
}
else {
// TODO: support a single number as index in case the matrix is a vector
throw new TypeError('Unsupported type of index ' + type(index));
throw new TypeError('Unsupported type of index ' + math.typeof(index));
}
};
/**
* Get a value or a set of values from the matrix.
* Indexes are zero-based.
* @param {Array | Vector | Matrix} index
* @param {Array | Range | Matrix} index
* @param {*} value
* @return {Matrix} itself
*/
@ -1147,10 +1147,7 @@ Matrix.prototype.set = function (index, value) {
}
index = index.toVector();
}
if (index instanceof Vector) {
index = index.valueOf();
}
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
if (value instanceof Matrix || value instanceof Range) {
value = value.valueOf();
}
@ -1192,7 +1189,7 @@ Matrix.prototype.set = function (index, 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));
throw new TypeError('Unsupported type of index ' + math.typeof(index));
}
return this;
@ -1262,12 +1259,12 @@ Matrix.prototype.isScalar = function () {
};
/**
* Create a Vector with a copy of the data of the Matrix
* Create a vector with a copy of the data of the Matrix
* Returns null if the Matrix does not contain a vector
*
* 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.
* return {Vector | null} vector
* return {Array | null} vector
*/
Matrix.prototype.toVector = function () {
var count = 0;
@ -1285,10 +1282,10 @@ Matrix.prototype.toVector = function () {
// scalar or empty
var scalar = this.toScalar();
if (scalar) {
return new Vector([scalar]);
return [scalar];
}
else {
return new Vector();
return [];
}
}
else if (count == 1) {
@ -1298,7 +1295,7 @@ Matrix.prototype.toVector = function () {
index[dim] = i;
vector[i] = clone(this.get(index));
}
return new Vector(vector);
return vector;
}
else {
// count > 1, this is no vector
@ -1386,7 +1383,6 @@ function isInteger(value) {
* range.map(function (x) {
* return math.sin(x);
* });
* range.toVector();
* range.toArray();
*
* Example usage:
@ -1498,18 +1494,10 @@ Range.prototype.map = function (callback) {
* Create a Matrix with a copy of the Ranges data
* @return {Matrix} matrix
*/
Vector.prototype.toMatrix = function () {
Range.prototype.toMatrix = function () {
return new Matrix(this.toArray());
};
/**
* Create a Vector with a copy of the Ranges data
* @return {Vector} vector
*/
Range.prototype.toVector = function () {
return new Vector(this.toArray());
};
/**
* Create an Array with a copy of the Ranges data
* @returns {Array} array
@ -1522,6 +1510,45 @@ Range.prototype.toArray = function () {
return array;
};
/**
* Create an array with a copy of the Ranges data.
* This method is equal to Range.toArray, and is available for compatibility
* with Matrix.
* @return {Array} vector
*/
Range.prototype.toVector = Range.prototype.toArray;
/**
* Test if the range contains a vector. For a range, this is always the case
* return {boolean} isVector
*/
Range.prototype.isVector = function () {
return true;
};
/**
* Create a scalar with a copy of the data of the Range
* Will return null if the range does not consist of a scalar value
* @return {* | null} scalar
*/
Range.prototype.toScalar = function () {
var array = this.toArray();
if (array.length == 1) {
return array[0];
}
else {
return null;
}
};
/**
* Test whether the matrix is a scalar.
* @return {boolean} isScalar
*/
Range.prototype.isScalar = function () {
return (this.size()[0] == 1);
};
/**
* Get the primitive value of the Range, a one dimensional array
* @returns {Array} array
@ -2207,281 +2234,6 @@ Unit.UNITS = [
{'name': 'bytes', 'base': BASE_UNITS.BIT, 'prefixes': PREFIXES.BINARY_LONG, 'value': 8, 'offset': 0}
];
/**
* @constructor Vector
* A Vector is a wrapper around an Array. A vector can hold a one dimensional
* array. A vector can be constructed as:
* var vector = new Vector(data)
*
* 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]);
* vector.resize(6, -1);
* vector.set(2, 9);
* vector.valueOf(); // [4, 5, 9, 7, -1, -1]
* vector.get([3, 4]) // [7, -1]
*
* @param {Array | Matrix | Vector | Range} [data] A one dimensional array
*/
function Vector(data) {
if (this.constructor != Vector) {
throw new SyntaxError(
'Vector constructor must be called with the new operator');
}
if (data instanceof Matrix) {
// clone data from Matrix
this._data = data.toVector();
}
else if (data instanceof Vector || data instanceof Range) {
// 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) {
// unsupported type
throw new TypeError('Unsupported type of data (' + math.typeof(data) + ')');
}
else {
// nothing provided
this._data = [];
}
// verify whether the data is a one dimensional array
this._size = util.size(this._data);
if (this._size.length > 1) {
throw new Error('Vector can only contain one dimension ' +
'(size: ' + format(this._size) + ')');
}
}
math.type.Vector = Vector;
/**
* Resize the vector
* @param {Number | Number[]} size A positive integer value, or an array
* containing one integer value.
* @param {*} [defaultValue] Default value, filled in on new entries.
* If not provided, the vector will be filled
* with zeros.
*/
Vector.prototype.resize = function (size, defaultValue) {
size = size.valueOf();
if (size instanceof Array) {
if (size.length > 1) {
throw new RangeError('Cannot resize a vector to multiple dimensions ' +
'(size: ' + format(size) + ')');
}
this.resize(size[0], defaultValue);
}
else {
if (!isNumber(size) || !isInteger(size) || size < 0) {
throw new TypeError('Positive integer expected as size in method resize');
}
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];
}
};
/**
* get a value or a subset of the vector. Throws an RangeError when index is
* out of range.
* Indexes are zero-based.
* @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);
});
}
else {
if (!isNumber(index) || !isInteger(index) || index < 0) {
throw new TypeError('Positive integer expected as index in method get');
}
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 values in the vector.
* Indexes are zero-based.
* @param {Number | Array | Matrix | Vector | Range} index
* @param {* | Array | Matrix | Vector | Range} value
* @return {Vector} itself
*/
Vector.prototype.set = function (index, value) {
var me = this;
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 Range || index instanceof Array) {
if (value instanceof Array) {
if (size(index) != value.length) {
throw new RangeError('Dimension mismatch ' +
'(' + size(index) + ' != ' + value.length + ')');
}
index.forEach(function (v, i) {
me._set(v, value[i]);
});
}
else {
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);
}
}
return this;
};
/**
* Set a single value
* @param {Number} index
* @param {*} value
* @private
*/
Vector.prototype._set = function (index, value) {
if (index > this._data.length) {
this.resize(index);
}
this._data[index] = value;
};
/**
* Create a clone of the vector
* @return {Vector} clone
*/
Vector.prototype.clone = function () {
var vector = new Vector();
vector._data = clone(this._data);
return vector;
};
/**
* Retrieve the size of the vector.
* The size of the vector will be validated too
* @returns {Number[]} size
*/
Vector.prototype.size = function () {
return this._size;
};
// TODO: implement Vector.map
// TODO: implement Vector.forEach
/**
* Create a Scalar with a copy of the Vectors data
* @return {* | null} scalar
*/
Vector.prototype.toScalar = function () {
if (this._data.length == 1) {
return clone(this._data[0]);
}
else {
return null;
}
};
/**
* Test whether the vector is a scalar.
* @return {boolean} isScalar
*/
Vector.prototype.isScalar = function () {
return (this._data.length <= 1);
};
/**
* Create a Matrix with a copy of the Vectors data
* @return {Matrix} matrix
*/
Vector.prototype.toMatrix = function () {
return new Matrix(this.toArray());
};
/**
* Create an Array with a copy of the Vectors data
* @returns {Array} array
*/
Vector.prototype.toArray = function () {
return clone(this._data);
};
/**
* Get the primitive value of the Vector: a one dimensional array
* @returns {Array} array
*/
Vector.prototype.valueOf = function () {
return this._data;
};
/**
* Get a string representation of the vector
* @returns {String} str
*/
Vector.prototype.toString = function () {
return util.formatArray(this._data);
};
/**
* mathjs constants
*/
@ -4800,7 +4552,7 @@ math.complex = complex;
* m.valueOf(); // [[1, 2], [3, 4], [5, 5]]
* m.get([1, 0]) // 3
*
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
* @param {Array | Matrix | Range} [data] A multi dimensional array
* @return {Matrix} matrix
*/
function matrix(data) {
@ -4945,33 +4697,6 @@ function unit(args) {
math.unit = unit;
/**
* Create a vector. The function creates a new math.type.Vector object.
*
* The method accepts the following arguments:
* vector() creates an empty vector
* vector(data) creates a vector with initial data.
*
* Example usage:
* var v = math.vector([4, 5, 6, 7]);
* v.resize(6, -1);
* v.set(2, 9);
* v.valueOf(); // [4, 5, 9, 7, -1, -1]
* v.get([3, 4]) // [7, -1]
*
* @param {Array | Matrix | Vector | Range} [data]
* @return {Vector} vector
*/
function vector(data) {
if (arguments.length > 1) {
throw newArgumentsError('vector', arguments.length, 0, 1);
}
return new Vector(data);
}
math.vector = vector;
/**
* Create a workspace. The function creates a new math.expr.Workspace object.
*
@ -5015,9 +4740,9 @@ math.workspace = workspace;
* diag(v, k)
* diag(X)
* diag(X, k)
* @param {Number | Matrix | Vector | Array} x
* @param {Number | Matrix | Array} x
* @param {Number} [k]
* @return {Matrix | Vector} matrix
* @return {Matrix} matrix
*/
function diag (x, k) {
var data, vector, i, iMax;
@ -5037,55 +4762,48 @@ function diag (x, k) {
var kSuper = k > 0 ? k : 0;
var kSub = k < 0 ? -k : 0;
if (x instanceof Matrix) {
if (x.isVector()) {
x = x.toVector();
}
}
else if (x instanceof Vector) {
// nothing to do
}
else if (x instanceof Range) {
x = x.toVector();
}
else if (x instanceof Array) {
// convert to matrix
if (!(x instanceof Matrix) && !(x instanceof Range)) {
x = new Matrix(x);
if (x.isVector()) {
x = x.toVector();
}
}
else {
x = new Matrix(x);
if (x.isVector()) {
x = x.toVector();
}
}
if (x instanceof Vector) {
// create diagonal matrix
vector = x.valueOf();
var matrix = new Matrix();
matrix.resize([vector.length + kSub, vector.length + kSuper]);
data = matrix.valueOf();
iMax = vector.length;
for (i = 0; i < iMax; i++) {
data[i + kSub][i + kSuper] = clone(vector[i]);
}
return matrix;
// get as array when the matrix is a vector
var s;
if (x.isVector()) {
x = x.toVector();
s = [x.length];
}
else {
// get diagonal from matrix
var s = x.size();
if (s.length != 2) {
s = x.size();
}
switch (s.length) {
case 1:
// x is a vector. create diagonal matrix
vector = x.valueOf();
var matrix = new Matrix();
matrix.resize([vector.length + kSub, vector.length + kSuper]);
data = matrix.valueOf();
iMax = vector.length;
for (i = 0; i < iMax; i++) {
data[i + kSub][i + kSuper] = clone(vector[i]);
}
return matrix;
break;
case 2:
// x is a matrix get diagonal from matrix
vector = [];
data = x.valueOf();
iMax = Math.min(s[0] - kSub, s[1] - kSuper);
for (i = 0; i < iMax; i++) {
vector[i] = clone(data[i + kSub][i + kSuper]);
}
return new Matrix(vector);
break;
default:
throw new RangeError('Matrix for function diag must be 2 dimensional');
}
vector = [];
data = x.valueOf();
iMax = Math.min(s[0] - kSub, s[1] - kSuper);
for (i = 0; i < iMax; i++) {
vector[i] = clone(data[i + kSub][i + kSuper]);
}
return new Vector(vector);
}
}
@ -5121,7 +4839,7 @@ diag.doc = {
};
/**
* Create an identity matrix with size m x n, identity(m [, n])
* @param {...Number | Matrix | Vector | Array} size
* @param {...Number | Matrix | Array} size
* @return {Matrix} matrix
*/
function identity (size) {
@ -5244,7 +4962,7 @@ ones.doc = {
]
};
/**
* Calculate the size of a vector, matrix, or scalar. size(x)
* Calculate the size of a matrix. size(x)
* @param {Number | Complex | Array} x
* @return {Number | Complex | Array} res
*/
@ -5265,7 +4983,7 @@ function size (x) {
return util.size(x);
}
if (x instanceof Matrix || x instanceof Vector || x instanceof Range) {
if (x instanceof Matrix || x instanceof Range) {
return x.size();
}

6
math.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -13,7 +13,7 @@
* m.valueOf(); // [[1, 2], [3, 4], [5, 5]]
* m.get([1, 0]) // 3
*
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
* @param {Array | Matrix | Range} [data] A multi dimensional array
* @return {Matrix} matrix
*/
function matrix(data) {

View File

@ -1,26 +0,0 @@
/**
* Create a vector. The function creates a new math.type.Vector object.
*
* The method accepts the following arguments:
* vector() creates an empty vector
* vector(data) creates a vector with initial data.
*
* Example usage:
* var v = math.vector([4, 5, 6, 7]);
* v.resize(6, -1);
* v.set(2, 9);
* v.valueOf(); // [4, 5, 9, 7, -1, -1]
* v.get([3, 4]) // [7, -1]
*
* @param {Array | Matrix | Vector | Range} [data]
* @return {Vector} vector
*/
function vector(data) {
if (arguments.length > 1) {
throw newArgumentsError('vector', arguments.length, 0, 1);
}
return new Vector(data);
}
math.vector = vector;

View File

@ -4,9 +4,9 @@
* diag(v, k)
* diag(X)
* diag(X, k)
* @param {Number | Matrix | Vector | Array} x
* @param {Number | Matrix | Array} x
* @param {Number} [k]
* @return {Matrix | Vector} matrix
* @return {Matrix} matrix
*/
function diag (x, k) {
var data, vector, i, iMax;
@ -26,55 +26,48 @@ function diag (x, k) {
var kSuper = k > 0 ? k : 0;
var kSub = k < 0 ? -k : 0;
if (x instanceof Matrix) {
if (x.isVector()) {
x = x.toVector();
}
}
else if (x instanceof Vector) {
// nothing to do
}
else if (x instanceof Range) {
x = x.toVector();
}
else if (x instanceof Array) {
// convert to matrix
if (!(x instanceof Matrix) && !(x instanceof Range)) {
x = new Matrix(x);
if (x.isVector()) {
x = x.toVector();
}
}
else {
x = new Matrix(x);
if (x.isVector()) {
x = x.toVector();
}
}
if (x instanceof Vector) {
// create diagonal matrix
vector = x.valueOf();
var matrix = new Matrix();
matrix.resize([vector.length + kSub, vector.length + kSuper]);
data = matrix.valueOf();
iMax = vector.length;
for (i = 0; i < iMax; i++) {
data[i + kSub][i + kSuper] = clone(vector[i]);
}
return matrix;
// get as array when the matrix is a vector
var s;
if (x.isVector()) {
x = x.toVector();
s = [x.length];
}
else {
// get diagonal from matrix
var s = x.size();
if (s.length != 2) {
s = x.size();
}
switch (s.length) {
case 1:
// x is a vector. create diagonal matrix
vector = x.valueOf();
var matrix = new Matrix();
matrix.resize([vector.length + kSub, vector.length + kSuper]);
data = matrix.valueOf();
iMax = vector.length;
for (i = 0; i < iMax; i++) {
data[i + kSub][i + kSuper] = clone(vector[i]);
}
return matrix;
break;
case 2:
// x is a matrix get diagonal from matrix
vector = [];
data = x.valueOf();
iMax = Math.min(s[0] - kSub, s[1] - kSuper);
for (i = 0; i < iMax; i++) {
vector[i] = clone(data[i + kSub][i + kSuper]);
}
return new Matrix(vector);
break;
default:
throw new RangeError('Matrix for function diag must be 2 dimensional');
}
vector = [];
data = x.valueOf();
iMax = Math.min(s[0] - kSub, s[1] - kSuper);
for (i = 0; i < iMax; i++) {
vector[i] = clone(data[i + kSub][i + kSuper]);
}
return new Vector(vector);
}
}

View File

@ -1,6 +1,6 @@
/**
* Create an identity matrix with size m x n, identity(m [, n])
* @param {...Number | Matrix | Vector | Array} size
* @param {...Number | Matrix | Array} size
* @return {Matrix} matrix
*/
function identity (size) {

View File

@ -1,5 +1,5 @@
/**
* Calculate the size of a vector, matrix, or scalar. size(x)
* Calculate the size of a matrix. size(x)
* @param {Number | Complex | Array} x
* @return {Number | Complex | Array} res
*/
@ -20,7 +20,7 @@ function size (x) {
return util.size(x);
}
if (x instanceof Matrix || x instanceof Vector || x instanceof Range) {
if (x instanceof Matrix || x instanceof Range) {
return x.size();
}

View File

@ -16,7 +16,7 @@
* matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
* matrix.get([1, 0]) // 3
*
* @param {Array | Matrix | Vector | Range} [data] A multi dimensional array
* @param {Array | Matrix | Range} [data] A multi dimensional array
*/
function Matrix(data) {
if (this.constructor != Matrix) {
@ -24,8 +24,8 @@ function Matrix(data) {
'Matrix constructor must be called with the new operator');
}
if (data instanceof Matrix || data instanceof Vector || data instanceof Range) {
// clone data from Vector, Matrix, or Range
if (data instanceof Matrix || data instanceof Range) {
// clone data from a Matrix or Range
this._data = data.toArray();
}
else if (data instanceof Array) {
@ -50,7 +50,7 @@ math.type.Matrix = Matrix;
/**
* Get a value or a set of values from the matrix.
* Indexes are zero-based.
* @param {Array | Vector | Matrix} index
* @param {Array | Matrix} index
*/
Matrix.prototype.get = function (index) {
// TODO: support syntax Matrix.get(m,n,p, ...)
@ -63,8 +63,8 @@ Matrix.prototype.get = function (index) {
}
index = index.toVector();
}
if (index instanceof Vector) {
index = index.valueOf();
if (index instanceof Range) {
index = index.toArray();
}
if (index instanceof Array) {
@ -87,14 +87,14 @@ Matrix.prototype.get = function (index) {
}
else {
// TODO: support a single number as index in case the matrix is a vector
throw new TypeError('Unsupported type of index ' + type(index));
throw new TypeError('Unsupported type of index ' + math.typeof(index));
}
};
/**
* Get a value or a set of values from the matrix.
* Indexes are zero-based.
* @param {Array | Vector | Matrix} index
* @param {Array | Range | Matrix} index
* @param {*} value
* @return {Matrix} itself
*/
@ -109,10 +109,7 @@ Matrix.prototype.set = function (index, value) {
}
index = index.toVector();
}
if (index instanceof Vector) {
index = index.valueOf();
}
if (value instanceof Matrix || value instanceof Vector || value instanceof Range) {
if (value instanceof Matrix || value instanceof Range) {
value = value.valueOf();
}
@ -154,7 +151,7 @@ Matrix.prototype.set = function (index, 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));
throw new TypeError('Unsupported type of index ' + math.typeof(index));
}
return this;
@ -224,12 +221,12 @@ Matrix.prototype.isScalar = function () {
};
/**
* Create a Vector with a copy of the data of the Matrix
* Create a vector with a copy of the data of the Matrix
* Returns null if the Matrix does not contain a vector
*
* 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.
* return {Vector | null} vector
* return {Array | null} vector
*/
Matrix.prototype.toVector = function () {
var count = 0;
@ -247,10 +244,10 @@ Matrix.prototype.toVector = function () {
// scalar or empty
var scalar = this.toScalar();
if (scalar) {
return new Vector([scalar]);
return [scalar];
}
else {
return new Vector();
return [];
}
}
else if (count == 1) {
@ -260,7 +257,7 @@ Matrix.prototype.toVector = function () {
index[dim] = i;
vector[i] = clone(this.get(index));
}
return new Vector(vector);
return vector;
}
else {
// count > 1, this is no vector

View File

@ -15,7 +15,6 @@
* range.map(function (x) {
* return math.sin(x);
* });
* range.toVector();
* range.toArray();
*
* Example usage:
@ -127,18 +126,10 @@ Range.prototype.map = function (callback) {
* Create a Matrix with a copy of the Ranges data
* @return {Matrix} matrix
*/
Vector.prototype.toMatrix = function () {
Range.prototype.toMatrix = function () {
return new Matrix(this.toArray());
};
/**
* Create a Vector with a copy of the Ranges data
* @return {Vector} vector
*/
Range.prototype.toVector = function () {
return new Vector(this.toArray());
};
/**
* Create an Array with a copy of the Ranges data
* @returns {Array} array
@ -151,6 +142,45 @@ Range.prototype.toArray = function () {
return array;
};
/**
* Create an array with a copy of the Ranges data.
* This method is equal to Range.toArray, and is available for compatibility
* with Matrix.
* @return {Array} vector
*/
Range.prototype.toVector = Range.prototype.toArray;
/**
* Test if the range contains a vector. For a range, this is always the case
* return {boolean} isVector
*/
Range.prototype.isVector = function () {
return true;
};
/**
* Create a scalar with a copy of the data of the Range
* Will return null if the range does not consist of a scalar value
* @return {* | null} scalar
*/
Range.prototype.toScalar = function () {
var array = this.toArray();
if (array.length == 1) {
return array[0];
}
else {
return null;
}
};
/**
* Test whether the matrix is a scalar.
* @return {boolean} isScalar
*/
Range.prototype.isScalar = function () {
return (this.size()[0] == 1);
};
/**
* Get the primitive value of the Range, a one dimensional array
* @returns {Array} array

View File

@ -1,274 +0,0 @@
/**
* @constructor Vector
* A Vector is a wrapper around an Array. A vector can hold a one dimensional
* array. A vector can be constructed as:
* var vector = new Vector(data)
*
* 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]);
* vector.resize(6, -1);
* vector.set(2, 9);
* vector.valueOf(); // [4, 5, 9, 7, -1, -1]
* vector.get([3, 4]) // [7, -1]
*
* @param {Array | Matrix | Vector | Range} [data] A one dimensional array
*/
function Vector(data) {
if (this.constructor != Vector) {
throw new SyntaxError(
'Vector constructor must be called with the new operator');
}
if (data instanceof Matrix) {
// clone data from Matrix
this._data = data.toVector();
}
else if (data instanceof Vector || data instanceof Range) {
// 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) {
// unsupported type
throw new TypeError('Unsupported type of data (' + math.typeof(data) + ')');
}
else {
// nothing provided
this._data = [];
}
// verify whether the data is a one dimensional array
this._size = util.size(this._data);
if (this._size.length > 1) {
throw new Error('Vector can only contain one dimension ' +
'(size: ' + format(this._size) + ')');
}
}
math.type.Vector = Vector;
/**
* Resize the vector
* @param {Number | Number[]} size A positive integer value, or an array
* containing one integer value.
* @param {*} [defaultValue] Default value, filled in on new entries.
* If not provided, the vector will be filled
* with zeros.
*/
Vector.prototype.resize = function (size, defaultValue) {
size = size.valueOf();
if (size instanceof Array) {
if (size.length > 1) {
throw new RangeError('Cannot resize a vector to multiple dimensions ' +
'(size: ' + format(size) + ')');
}
this.resize(size[0], defaultValue);
}
else {
if (!isNumber(size) || !isInteger(size) || size < 0) {
throw new TypeError('Positive integer expected as size in method resize');
}
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];
}
};
/**
* get a value or a subset of the vector. Throws an RangeError when index is
* out of range.
* Indexes are zero-based.
* @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);
});
}
else {
if (!isNumber(index) || !isInteger(index) || index < 0) {
throw new TypeError('Positive integer expected as index in method get');
}
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 values in the vector.
* Indexes are zero-based.
* @param {Number | Array | Matrix | Vector | Range} index
* @param {* | Array | Matrix | Vector | Range} value
* @return {Vector} itself
*/
Vector.prototype.set = function (index, value) {
var me = this;
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 Range || index instanceof Array) {
if (value instanceof Array) {
if (size(index) != value.length) {
throw new RangeError('Dimension mismatch ' +
'(' + size(index) + ' != ' + value.length + ')');
}
index.forEach(function (v, i) {
me._set(v, value[i]);
});
}
else {
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);
}
}
return this;
};
/**
* Set a single value
* @param {Number} index
* @param {*} value
* @private
*/
Vector.prototype._set = function (index, value) {
if (index > this._data.length) {
this.resize(index);
}
this._data[index] = value;
};
/**
* Create a clone of the vector
* @return {Vector} clone
*/
Vector.prototype.clone = function () {
var vector = new Vector();
vector._data = clone(this._data);
return vector;
};
/**
* Retrieve the size of the vector.
* The size of the vector will be validated too
* @returns {Number[]} size
*/
Vector.prototype.size = function () {
return this._size;
};
// TODO: implement Vector.map
// TODO: implement Vector.forEach
/**
* Create a Scalar with a copy of the Vectors data
* @return {* | null} scalar
*/
Vector.prototype.toScalar = function () {
if (this._data.length == 1) {
return clone(this._data[0]);
}
else {
return null;
}
};
/**
* Test whether the vector is a scalar.
* @return {boolean} isScalar
*/
Vector.prototype.isScalar = function () {
return (this._data.length <= 1);
};
/**
* Create a Matrix with a copy of the Vectors data
* @return {Matrix} matrix
*/
Vector.prototype.toMatrix = function () {
return new Matrix(this.toArray());
};
/**
* Create an Array with a copy of the Vectors data
* @returns {Array} array
*/
Vector.prototype.toArray = function () {
return clone(this._data);
};
/**
* Get the primitive value of the Vector: a one dimensional array
* @returns {Array} array
*/
Vector.prototype.valueOf = function () {
return this._data;
};
/**
* Get a string representation of the vector
* @returns {String} str
*/
Vector.prototype.toString = function () {
return util.formatArray(this._data);
};

View File

@ -102,7 +102,7 @@ var util = (function () {
* fn(n)
* fn(m, n, p, ...)
* fn([m, n, p, ...])
* @param {...Number | Array | Matrix | Vector} args
* @param {...Number | Array | Matrix} args
* @returns {Array} array
*/
util.argsToArray = function argsToArray(args) {
@ -118,7 +118,7 @@ var util = (function () {
if (array instanceof Matrix) {
array = array.toVector();
}
if (array instanceof Vector || array instanceof Range) {
if (array instanceof Range) {
array = array.valueOf();
}
if (!(array instanceof Array)) {
@ -479,7 +479,7 @@ var util = (function () {
// check the type of size
if (!(size instanceof Array)) {
throw new TypeError('Size must be an array (size is ' + type(size) + ')');
throw new TypeError('Size must be an array (size is ' + math.typeof(size) + ')');
}
// check whether size contains positive integers

View File

@ -19,7 +19,6 @@ assert.deepEqual(math.size('hello'), [5]);
assert.deepEqual(math.size(''), [0]);
assert.deepEqual(math.size(math.complex(2,3)), []);
assert.deepEqual(math.size(null), []);
assert.deepEqual(math.size(math.vector()), [0]);
assert.deepEqual(math.size(math.matrix()), [0]);
assert.deepEqual(math.size(math.range(2,5)), [4]);
// TODO: test whether math.size throws an error in case of invalid data or size
@ -33,7 +32,7 @@ assert.deepEqual(math.identity([2]).valueOf(), [[1,0],[0,1]]);
assert.deepEqual(math.identity(2,3).valueOf(), [[1,0,0],[0,1,0]]);
assert.deepEqual(math.identity(3,2).valueOf(), [[1,0],[0,1],[0,0]]);
assert.deepEqual(math.identity([3,2]).valueOf(), [[1,0],[0,1],[0,0]]);
assert.deepEqual(math.identity(math.vector([3,2])).valueOf(), [[1,0],[0,1],[0,0]]);
assert.deepEqual(math.identity(math.matrix([3,2])).valueOf(), [[1,0],[0,1],[0,0]]);
assert.deepEqual(math.identity(math.matrix([[3],[2]])).valueOf(), [[1,0],[0,1],[0,0]]);
assert.deepEqual(math.identity(3,3).valueOf(), [[1,0,0],[0,1,0],[0,0,1]]);
assert.throws(function () {math.identity(3,3,2);});
@ -47,7 +46,6 @@ assert.deepEqual(math.zeros(3).valueOf(), [[0,0,0],[0,0,0],[0,0,0]]);
assert.deepEqual(math.zeros(2,3).valueOf(), [[0,0,0],[0,0,0]]);
assert.deepEqual(math.zeros(3,2).valueOf(), [[0,0],[0,0],[0,0]]);
assert.deepEqual(math.zeros([3,2]).valueOf(), [[0,0],[0,0],[0,0]]);
assert.deepEqual(math.zeros(math.vector([3,2])).valueOf(), [[0,0],[0,0],[0,0]]);
assert.deepEqual(math.zeros(math.matrix([3,2])).valueOf(), [[0,0],[0,0],[0,0]]);
assert.deepEqual(math.zeros(math.matrix([[[3]],[[2]]])).valueOf(), [[0,0],[0,0],[0,0]]);
assert.deepEqual(math.zeros(2,2,2).valueOf(), [[[0,0],[0,0]],[[0,0],[0,0]]]);
@ -63,7 +61,6 @@ assert.deepEqual(math.ones(3).valueOf(), [[1,1,1],[1,1,1],[1,1,1]]);
assert.deepEqual(math.ones(2,3).valueOf(), [[1,1,1],[1,1,1]]);
assert.deepEqual(math.ones(3,2).valueOf(), [[1,1],[1,1],[1,1]]);
assert.deepEqual(math.ones([3,2]).valueOf(), [[1,1],[1,1],[1,1]]);
assert.deepEqual(math.ones(math.vector([3,2])).valueOf(), [[1,1],[1,1],[1,1]]);
assert.deepEqual(math.ones(math.matrix([3,2])).valueOf(), [[1,1],[1,1],[1,1]]);
assert.deepEqual(math.ones(math.matrix([[[3]],[[2]]])).valueOf(), [[1,1],[1,1],[1,1]]);
assert.deepEqual(math.ones(2,2,2).valueOf(), [[[1,1],[1,1]],[[1,1],[1,1]]]);

View File

@ -37,7 +37,7 @@ b = math.clone(a);
a.valueOf()[0][0] = 5;
assert.equal(b.valueOf()[0][0], 1);
a = math.vector([1, 2, new math.complex(2, 3), 4]);
a = math.matrix([1, 2, new math.complex(2, 3), 4]);
b = math.clone(a);
a.valueOf()[2].re = 5;
assert.equal(b.valueOf()[2].re, 2);

View File

@ -31,37 +31,37 @@ m = math.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]);
assert.deepEqual(m.toVector(), [1,2,3]);
m = math.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]);
assert.deepEqual(m.toVector(), [1,2,3]);
m = math.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]);
assert.deepEqual(m.toVector(), [1,2,3]);
m = math.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]);
assert.deepEqual(m.toVector(), [3]);
m = math.matrix([[]]);
assert.equal(m.isScalar(), true);
assert.equal(m.isVector(), true);
assert.deepEqual(m.size(), [0,0]);
assert.deepEqual(m.toVector().valueOf(), []);
assert.deepEqual(m.toVector(), []);
m = math.matrix();
assert.equal(m.isScalar(), true);
assert.equal(m.isVector(), true);
assert.deepEqual(m.size(), [0]);
assert.deepEqual(m.toVector().valueOf(), []);
assert.deepEqual(m.toVector(), []);
// test resizing
m = math.matrix([[1,2,3],[4,5,6]]);

View File

@ -1,36 +0,0 @@
// test data type Vector
var assert = require('assert');
var math = require('../../math.js');
var v = math.vector([3,4,5]);
assert.deepEqual(v.size(), [3]);
assert.deepEqual(v.get(2), 5);
assert.deepEqual(v.get([1,0]), [4,3]);
v.set(1, 400);
assert.deepEqual(v.valueOf(), [3,400,5]);
v.resize(5);
assert.deepEqual(v.valueOf(), [3,400,5,0,0]);
c = math.complex(2,3);
v.resize(7, c);
c.re = 4;
assert.deepEqual(v.valueOf(), [3,400,5,0,0, math.complex(2,3), math.complex(2,3)]);
v.resize(2);
assert.deepEqual(v.valueOf(), [3,400]);
v.set([4,5], [400, 500]);
assert.deepEqual(v.valueOf(), [3,400,0,0,400,500]);
v = math.vector([100]);
v.set(2, 200);
assert.deepEqual(v.valueOf(), [100, 0, 200]);
v.resize(1);
assert.deepEqual(v.valueOf(), [100]);
var s = v.toScalar();
assert.deepEqual(s, 100);
v = math.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