mathjs
Version:
Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.
120 lines (100 loc) • 3.95 kB
JavaScript
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = math.type.BigNumber,
Matrix = require('../../type/Matrix'),
Complex = require('../../type/Complex'),
Unit = require('../../type/Unit'),
collection = require('../../type/collection'),
deepEqual = util.object.deepEqual,
isNumber = util.number.isNumber,
isString = util.string.isString,
isBoolean = util['boolean'].isBoolean,
isComplex = Complex.isComplex,
isUnit = Unit.isUnit,
isCollection = collection.isCollection;
/**
* Execute a conditional expression.
*
* In case of a matrix or array, the test is done element wise, the
* true and false part can be either a matrix/array with the same size
* of the condition, or a scalar value.
*
* @param {Number | Boolean | String | Complex | BigNumber | Unit | Matrix | Array} condition
* The conditional expression
* @param {*} trueExpr The true expression
* @param {*} falseExpr The false expression
* @return {*} The evaluated return expression
*/
math.ifElse = function ifElse(condition, trueExpr, falseExpr) {
if (arguments.length != 3) {
throw new math.error.ArgumentsError('ifElse', arguments.length, 3);
}
if (isNumber(condition) || isBoolean(condition)) {
return condition ? trueExpr : falseExpr;
}
if (condition instanceof BigNumber) {
return condition.isZero() ? falseExpr : trueExpr;
}
if (isString(condition)) {
return condition ? trueExpr : falseExpr;
}
if (isComplex(condition)) {
return (condition.re || condition.im) ? trueExpr : falseExpr;
}
if (isUnit(condition)) {
return condition.value ? trueExpr : falseExpr;
}
if (condition === null || condition === undefined) {
return falseExpr;
}
if (isCollection(condition)) {
return _ifElseCollection(condition, trueExpr, falseExpr);
}
throw new math.error.UnsupportedTypeError('ifElse', math['typeof'](condition));
};
/**
* Execute the if-else condition element wise
* @param {Matrix | Array} condition
* @param {*} trueExpr
* @param {*} falseExpr
* @returns {*}
* @private
*/
function _ifElseCollection(condition, trueExpr, falseExpr) {
var asMatrix = (condition instanceof Matrix) ||
(trueExpr instanceof Matrix) ||
(falseExpr instanceof Matrix);
// change an array into a matrix
if (!(condition instanceof Matrix)) condition = new Matrix(condition);
// change the true expression into a matrix and check whether the size
// matches with the condition matrix
if (isCollection(trueExpr)) {
if (!(trueExpr instanceof Matrix)) trueExpr = new Matrix(trueExpr);
if (!deepEqual(condition.size(), trueExpr.size())) {
throw new RangeError('Dimension mismatch ([' +
condition.size().join(', ') + '] != [' +
trueExpr.size().join(', ')
+ '])');
throw new math.error.DimensionError(condition.size(), trueExpr.size());
}
}
// change the false expression into a matrix and check whether the size
// matches with the condition matrix
if (isCollection(falseExpr)) {
if (!(falseExpr instanceof Matrix)) falseExpr = new Matrix(falseExpr);
if (!deepEqual(condition.size(), falseExpr.size())) {
throw new math.error.DimensionError(condition.size(), falseExpr.size());
}
}
// do the actual conditional test element wise
var trueIsMatrix = trueExpr instanceof Matrix,
falseIsMatrix = falseExpr instanceof Matrix;
var result = condition.map(function (value, index) {
return math.ifElse(value,
trueIsMatrix ? trueExpr.get(index) : trueExpr,
falseIsMatrix ? falseExpr.get(index) : falseExpr
);
});
return asMatrix ? result : result.valueOf();
}
};