// Generated by CoffeeScript 1.10.0
var arrayFns, checkCanMultiply, checkSizesMatch, compose, createLiftFunctions, expect, lift1, lift2, lift2Infix, liftAllOutputs, liftInput, ref, ref1, t;
expect = require('chai').expect;
/**
* API for dealing with matrices as wrapped functions.
* @module matrixy
*/
arrayFns = require('./arrays');
expect = require('chai').expect;
ref = require('./functional_utils'), compose = ref.compose, createLiftFunctions = ref.createLiftFunctions;
/*
* Internal reference to module.exports.
* @private
*/
t = this;
ref1 = createLiftFunctions({
wrap: function(arrays) {
if (Array.isArray(arrays)) {
return t.createMatrix(arrays);
} else {
return arrays;
}
},
unwrap: function(matrix) {
if (typeof matrix === 'function') {
return matrix();
} else {
return matrix;
}
}
}), liftInput = ref1.liftInput, lift1 = ref1.lift1, lift2 = ref1.lift2, lift2Infix = ref1.lift2Infix, liftAllOutputs = ref1.liftAllOutputs;
/**
* A Matrix. Can be given a {@link module:matrixy.MatrixOperation}.
* @callback module:matrixy.Matrix
* @param {module:matrixy.MatrixOperation} [op]
* @return {Array.<Array.<Number>>|*} Internal 2D array if no params given, else result of op.
*/
/**
* Operation on a {@link module:matrixy.Matrix}.
* @callback module:matrixy.MatrixOperation
* @param {module:matrixy.Matrix} matrix
* @return {*}
*/
/**
* Create a {@link module:matrixy.Matrix} from a 2D array.
* @param {!Array.<Array.<Number>>} arrays - 2D array
* @return {module:matrixy.Matrix}
*/
this.createMatrix = function(arrays) {
var wrapper;
expect(arrays, 'createMatrix').to.not.be.empty;
expect(arrays[0], 'createMatrix').to.not.be.empty;
/**
* @param {module:matrixy.MatrixOperation} [op]
* @return {Array.<Array.<Number>>|*} Internal 2D array if no params given, else result of op.
*/
return wrapper = function(op) {
return (typeof op === "function" ? op(wrapper) : void 0) || arrays;
};
};
/**
* Create an immutable {@link module:matrixy.Matrix} from a 2D array.
* All {@link module:matrixy.MatrixOperation}s will be performed on a copy of the 2D array.
* @param {!Array.<Array.<Number>>} arrays
* @return {module:matrixy.Matrix}
*/
this.createImmutableMatrix = function(arrays) {
var wrapper;
return wrapper = function(op) {
return (typeof op === "function" ? op(wrapper) : void 0) || arrayFns.copy(arrays);
};
};
/**
* Create an identity {@link module:matrixy.Matrix} of the given size.
* @function
* @param {!Integer} size
* @return {module:matrixy.Matrix}
*/
this.createIdentityMatrix = compose(t.createMatrix, arrayFns.createIdentity);
/**
* Create a blank {@link module:matrixy.Matrix} of the given size.
* @function
* @param {!Integer} size
* @return {module:matrixy.Matrix}
*/
this.createBlankMatrix = compose(t.createMatrix, arrayFns.createBlank);
/**
* Return a copy of the given Matrix.
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.Matrix}
*/
this.copy = function(matrix) {
return t.createMatrix(arrayFns.copy(matrix()));
};
/**
* Get an entry in the matrix at position (row, col).
* @param {Integer} row
* @param {Integer} col
* @return {Number}
*/
this.get = function(row, col) {
return function(m) {
return m()[row][col];
};
};
/**
* Set an entry in the matrix to a given value.
* @param {Integer} row
* @param {Integer} col
* @return {module:matrixy~setter}
*/
this.set = function(row, col) {
/**
* @namespace module:matrixy~setter
*/
return {
/**
* Set to the given value.
* @memberOf module:matrixy~setter
* @param {Number} value
* @return {module:matrixy.MatrixOperation}
*/
to: function(value) {
return function(m) {
return m()[row][col] = value;
};
},
/**
* Equivalent to the += operator.
* @memberOf module:matrixy~setter
* @param {Number} value
* @return {module:matrixy.MatrixOperation}
*/
plusEquals: function(value) {
return function(m) {
return m()[row][col] += value;
};
}
};
};
/**
* Get the number of rows in the given matrix.
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Number}
*/
this.numOfRowsOf = liftInput(arrayFns.getNumOfRows);
/**
* Get the number of columns in the given matrix.
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Number}
*/
this.numOfColsOf = liftInput(arrayFns.getNumOfColumns);
/**
* @see {@link module:arrays.getDimensions}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Array.<Integer>} e.g. [2, 3] for a 2x3 matrix
*/
this.getDimensionsOf = liftInput(arrayFns.getDimensions);
/**
* @see {@link module:arrays.getSize}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {String}
*/
this.sizeOf = liftInput(arrayFns.getSize);
/**
* @see {@link module:arrays.isLowerTriangular}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Boolean}
*/
this.isLowerTriangular = liftInput(arrayFns.isLowerTriangular);
/**
* @see {@link module:arrays.isUpperTriangular}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Boolean}
*/
this.isUpperTriangular = liftInput(arrayFns.isUpperTriangular);
/**
* Get the wrapped 2D arrays of a {@link module:matrixy.Matrix}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Array.<Array.<Number>>}
*/
this.innerArraysOf = liftInput(function(arrays) {
return arrays;
});
/*
* @private
* @param {Array.<Array.<Number>>} a1
* @param {Array.<Array.<Number>>} a2
*/
checkSizesMatch = function(a1, a2) {
var size1, size2;
size1 = arrayFns.getSize(a1);
size2 = arrayFns.getSize(a2);
return expect(size1, 'Matrix size').to.equal(size2);
};
/*
* @private
* @param {Array.<Array.<Number>>} a1
* @param {Array.<Array.<Number>>} a2
*/
checkCanMultiply = function(a1, a2) {
var numOfColsIn1, numOfRowsIn2, size1, size2;
numOfColsIn1 = arrayFns.getNumOfColumns(a1);
numOfRowsIn2 = arrayFns.getNumOfRows(a2);
if (numOfColsIn1 !== numOfRowsIn2) {
size1 = arrayFns.getSize(a1);
size2 = arrayFns.getSize(a2);
throw {
name: 'IllegalArgumentException',
message: "Can't multiply a " + size1 + " matrix by a " + size2 + " matrix."
};
}
};
/**
* Infix function to add two Matrices.
* @example
* c = a(plus(b)); // JavaScript
* c = a plus b # CoffeeScript
* @function
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.MatrixOperation}
*/
this.plus = lift2Infix(function(a1, a2) {
checkSizesMatch(a1, a2);
return arrayFns.add(a1, a2);
});
/**
* Infix function to subtract a Matrix from another
* @example
* c = a(minus(b)); // JavaScript
* c = a minus b # CoffeeScript
* @function
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.MatrixOperation}
*/
this.minus = lift2Infix(function(a1, a2) {
checkSizesMatch(a1, a2);
return arrayFns.subtract(a1, a2);
});
/**
* Infix function to multiply two Matrices.
* @example
* c = a(times(b)); // JavaScript
* c = a times b # CoffeeScript
* @function
* @param {(module:matrixy.Matrix|Number)} matrix
* @return {module:matrixy.MatrixOperation}
*/
this.times = lift2Infix(function(a1, a2) {
if (typeof a2 !== 'number') {
checkCanMultiply(a1, a2);
}
return arrayFns.multiply(a1, a2);
});
/**
* Infix function to divide a Matrix by another
* @example
* c = a(dividedBy(b)); // JavaScript
* c = a dividedBy b # CoffeeScript
* @function
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.MatrixOperation}
*/
this.dividedBy = lift2Infix(arrayFns.divide);
/**
* @typedef module:matrixy.LUP
* @type {object}
* @property {module:matrixy.Matrix} l - Lower triangular matrix.
* @property {module:matrixy.Matrix} u - Upper triangular matrix.
* @property {module:matrixy.Matrix} p - Permutation matrix.
*/
/**
* Decompose this matrix into an LU pair.
* @see {@link module:arrays.decompose}
* @function
* @param {module:matrixy.Matrix} matrix
* @return {LUP}
*/
this.decompose = liftAllOutputs(arrayFns.decompose);
/**
* Solve the matrix equation Ax = b for x with matrix size N.
* @see {@link module:arrays.solve}
* @function
* @param {module:matrixy.Matrix} A - NxN
* @param {module:matrixy.Matrix} b - Nx1
* @return {module:matrixy.Matrix} Nx1
*/
this.solve = lift2(arrayFns.solve);
/**
* Return a transposed version of the given {@link module:matrixy.Matrix}.
* @function
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.Matrix} Transposed matrix.
*/
this.transpose = lift1(arrayFns.transpose);
/**
* Return an inverted version of the given {@link module:matrixy.Matrix}.
* @function
* @param {module:matrixy.Matrix} matrix
* @return {module:matrixy.Matrix} Inverted matrix.
*/
this.invert = lift1(arrayFns.invert);
/**
* Is it possible to invert the given 2D array?
* @function
* @param {module:matrixy.Matrix} matrix
* @return {Boolean}
*/
this.isInvertible = lift1(arrayFns.isInvertible);
/**
* Return the determinant of the given {@link module:matrixy.Matrix}.
* @function
* @param {module:matrixy.Matrix} matrix - Square matrix
* @return {Number}
*/
this.determinantOf = lift1(function(arrays) {
expect(arrays).to.satisfy(arrayFns.isSquare, 'Can only find determinant of a square matrix');
return arrayFns.determinant(arrays);
});