element wise operations

This commit is contained in:
rjbaucells 2015-04-30 20:17:24 -04:00
parent 4ab8a7e248
commit b7ea83e0f2
4 changed files with 246 additions and 27 deletions

View File

@ -1,7 +1,9 @@
'use strict';
function factory (type, config, load, typed) {
var collection = load(require('../../type/collection'));
var matrix = load(require('../construction/matrix'));
var elementWiseOperations = load(require('../../type/matrix/util/elementWiseOperations'));
/**
* Calculates the modulus, the remainder of an integer division.
@ -39,18 +41,100 @@ function factory (type, config, load, typed) {
* @return {Number | BigNumber | Array | Matrix} Returns the remainder of `x` divided by `y`.
*/
var mod = typed('mod', {
'number, number': _mod,
'BigNumber, BigNumber': function (x, y) {
return y.isZero() ? x : x.mod(y);
},
'Matrix, Matrix': function (x, y) {
// result
var c;
'Array | Matrix, any': function (x, y) {
return collection.deepMap2(x, y, mod);
// process matrix storage
switch (x.storage()) {
case 'sparse':
switch (y.storage()) {
case 'sparse':
// mod(sparse, sparse)
c = elementWiseOperations.algorithm5(x, y, mod, false);
break;
default:
// mod(sparse, dense)
c = elementWiseOperations.algorithm2(y, x, mod, true);
break;
}
break;
default:
switch (y.storage()) {
case 'sparse':
// mod(dense, sparse)
c = elementWiseOperations.algorithm3(x, y, mod, false);
break;
default:
// mod(dense, dense)
c = elementWiseOperations.algorithm11(x, y, mod, false);
break;
}
break;
}
return c;
},
'Array, Array': function (x, y) {
// use matrix implementation
return mod(matrix(x), matrix(y)).valueOf();
},
'any, Array | Matrix': function (x, y) {
return collection.deepMap2(x, y, mod);
'Array, Matrix': function (x, y) {
// use matrix implementation
return mod(matrix(x), y);
},
'Matrix, Array': function (x, y) {
// use matrix implementation
return mod(x, matrix(y));
},
'Matrix, any': function (x, y) {
// result
var c;
// check storage format
switch (x.storage()) {
case 'sparse':
c = elementWiseOperations.algorithm9(x, y, mod, false);
break;
default:
c = elementWiseOperations.algorithm12(x, y, mod, false);
break;
}
return c;
},
'any, Matrix': function (x, y) {
// result
var c;
// check storage format
switch (y.storage()) {
case 'sparse':
c = elementWiseOperations.algorithm10(y, x, mod, true);
break;
default:
c = elementWiseOperations.algorithm12(y, x, mod, true);
break;
}
return c;
},
'Array, any': function (x, y) {
// use matrix implementation
return elementWiseOperations.algorithm12(matrix(x), y, mod, false).valueOf();
},
'any, Array': function (x, y) {
// use matrix implementation
return elementWiseOperations.algorithm12(matrix(y), x, mod, true).valueOf();
}
});

View File

@ -4,7 +4,12 @@ var isInteger = require('../../util/number').isInteger;
var toFixed = require('../../util/number').toFixed;
function factory (type, config, load, typed) {
var collection = load(require('../../type/collection'));
var matrix = load(require('../construction/matrix'));
var equal = load(require('../relational/equal'));
var zeros = load(require('../matrix/zeros'));
var elementWiseOperations = load(require('../../type/matrix/util/elementWiseOperations'));
/**
* Round a value towards the nearest integer.
@ -38,6 +43,7 @@ function factory (type, config, load, typed) {
* @return {Number | BigNumber | Complex | Array | Matrix} Rounded value
*/
var round = typed('round', {
'number': Math.round,
'number, number': function (x, n) {
@ -84,12 +90,49 @@ function factory (type, config, load, typed) {
return collection.deepMap(x, round, true);
},
'Array | Matrix, number | BigNumber': function (x, n) {
return collection.deepMap2(x, n, round);
'Matrix, number | BigNumber': function (x, y) {
// result
var c;
// check storage format
switch (x.storage()) {
case 'sparse':
c = elementWiseOperations.algorithm9(x, y, round, false);
break;
default:
c = elementWiseOperations.algorithm12(x, y, round, false);
break;
}
return c;
},
'number | Complex | BigNumber, Array | Matrix': function (x, n) {
return collection.deepMap2(x, n, round);
'number | Complex | BigNumber, Matrix': function (x, y) {
// check scalar is zero
if (!equal(x, 0)) {
// result
var c;
// check storage format
switch (y.storage()) {
case 'sparse':
c = elementWiseOperations.algorithm10(y, x, round, true);
break;
default:
c = elementWiseOperations.algorithm12(y, x, round, true);
break;
}
return c;
}
// do not execute algorithm, result will be a zero matrix
return zeros(y.size(), y.storage());
},
'Array, number | BigNumber': function (x, y) {
// use matrix implementation
return elementWiseOperations.algorithm12(matrix(x), y, round, false).valueOf();
},
'number | Complex | BigNumber, Array': function (x, y) {
// use matrix implementation
return elementWiseOperations.algorithm12(matrix(y), x, round, true).valueOf();
}
});

View File

@ -4,10 +4,11 @@ var approx = require('../../../tools/approx');
var math = require('../../../index');
var bignumber = math.bignumber;
var matrix = math.matrix;
var range = math.range;
var sparse = math.sparse;
var mod = math.mod;
describe('mod', function() {
it('should calculate the modulus of booleans correctly', function () {
assert.equal(mod(true, true), 0);
assert.equal(mod(false, true), 0);
@ -38,17 +39,17 @@ describe('mod', function() {
});
it('should throw an error if the modulus is negative', function() {
assert.throws(function () {mod(10, -4)});
assert.throws(function () {mod(10, -4);});
});
it('should throw an error if used with wrong number of arguments', function() {
assert.throws(function () {mod(1)}, /TypeError: Too few arguments/);
assert.throws(function () {mod(1,2,3)}, /TypeError: Too many arguments/);
assert.throws(function () {mod(1);}, /TypeError: Too few arguments/);
assert.throws(function () {mod(1,2,3);}, /TypeError: Too many arguments/);
});
it('should throw an error if used with wrong type of arguments', function() {
assert.throws(function () {mod(1, 'string')}, /TypeError: Unexpected type of argument/);
assert.throws(function () {mod('string', bignumber(2))}, /TypeError: Unexpected type of argument/);
assert.throws(function () {mod(1, 'string');}, /TypeError: Unexpected type of argument/);
assert.throws(function () {mod('string', bignumber(2));}, /TypeError: Unexpected type of argument/);
});
it('should calculate the modulus of bignumbers', function() {
@ -75,8 +76,8 @@ describe('mod', function() {
assert.deepEqual(mod(bignumber(0), 3), bignumber(0));
assert.deepEqual(mod(bignumber(7), 0), bignumber(7));
assert.throws(function () {mod(7/3, bignumber(2))}, /TypeError: Cannot implicitly convert a number with >15 significant digits to BigNumber/);
assert.throws(function () {mod(bignumber(7).div(3), 1/3)}, /TypeError: Cannot implicitly convert a number with >15 significant digits to BigNumber/);
assert.throws(function () {mod(7/3, bignumber(2));}, /TypeError: Cannot implicitly convert a number with >15 significant digits to BigNumber/);
assert.throws(function () {mod(bignumber(7).div(3), 1/3);}, /TypeError: Cannot implicitly convert a number with >15 significant digits to BigNumber/);
});
it('should calculate the modulus of mixed booleans and bignumbers', function() {
@ -87,24 +88,78 @@ describe('mod', function() {
});
it('should throw an error if used on complex numbers', function() {
assert.throws(function () {mod(math.complex(1,2), 3)}, TypeError);
assert.throws(function () {mod(3, math.complex(1,2))}, TypeError);
assert.throws(function () {mod(bignumber(3), math.complex(1,2))}, TypeError);
assert.throws(function () {mod(math.complex(1,2), 3);}, TypeError);
assert.throws(function () {mod(3, math.complex(1,2));}, TypeError);
assert.throws(function () {mod(bignumber(3), math.complex(1,2));}, TypeError);
});
it('should an throw an error if used on a string', function() {
assert.throws(function () {mod('string', 3)}, TypeError);
assert.throws(function () {mod(5, 'string')}, TypeError);
assert.throws(function () {mod('string', 3);}, TypeError);
assert.throws(function () {mod(5, 'string');}, TypeError);
});
it('should perform element-wise modulus on a matrix', function() {
approx.deepEqual(mod([-4,-3,-2,-1,0,1,2,3,4], 3), [2,0,1,2,0,1,2,0,1]);
approx.deepEqual(mod(matrix([-4,-3,-2,-1,0,1,2,3,4]), 3), matrix([2,0,1,2,0,1,2,0,1]));
describe('Array', function () {
it('should perform element-wise modulus on array and scalar', function() {
approx.deepEqual(mod([[-4, -3, 0, -1], [0, 1, 2, 3]], 3), [[2, 0, 0, 2], [0, 1, 2, 0]]);
approx.deepEqual(mod(3, [[4, 3], [2, 1]]), [[3, 0], [1, 0]]);
});
it('should perform element-wise modulus on array and array', function() {
approx.deepEqual(mod([[-40, -31], [11, -23]], [[3, 7], [1, 3]]), [[2, 4], [0, 1]]);
});
it('should perform element-wise modulus on array and dense matrix', function() {
approx.deepEqual(mod([[-40, -31], [11, -23]], matrix([[3, 7], [1, 3]])), matrix([[2, 4], [0, 1]]));
});
it('should perform element-wise modulus on array and sparse matrix', function() {
approx.deepEqual(mod([[-40, -31], [11, -23]], sparse([[3, 7], [1, 3]])), matrix([[2, 4], [0, 1]]));
});
});
describe('DenseMatrix', function () {
it('should perform element-wise modulus on dense matrix and scalar', function() {
approx.deepEqual(mod(matrix([[-4, -3, 0, -1], [0, 1, 2, 3]]), 3), matrix([[2, 0, 0, 2], [0, 1, 2, 0]]));
approx.deepEqual(mod(3, matrix([[4, 3], [2, 1]])), matrix([[3, 0], [1, 0]]));
});
it('should perform element-wise modulus on dense matrix and array', function() {
approx.deepEqual(mod(matrix([[-40, -31], [11, -23]]), [[3, 7], [1, 3]]), matrix([[2, 4], [0, 1]]));
});
it('should perform element-wise modulus on dense matrix and dense matrix', function() {
approx.deepEqual(mod(matrix([[-40, -31], [11, -23]]), matrix([[3, 7], [1, 3]])), matrix([[2, 4], [0, 1]]));
});
it('should perform element-wise modulus on dense matrix and sparse matrix', function() {
approx.deepEqual(mod(matrix([[-40, -31], [11, -23]]), sparse([[3, 7], [1, 3]])), matrix([[2, 4], [0, 1]]));
});
});
describe('SparseMatrix', function () {
it('should perform element-wise modulus on sparse matrix and scalar', function() {
approx.deepEqual(mod(sparse([[-4, -3, 0, -1], [0, 1, 2, 3]]), 3), sparse([[2, 0, 0, 2], [0, 1, 2, 0]]));
approx.deepEqual(mod(3, sparse([[4, 3], [2, 1]])), matrix([[3, 0], [1, 0]]));
});
it('should perform element-wise modulus on sparse matrix and array', function() {
approx.deepEqual(mod(sparse([[-40, -31], [11, -23]]), [[3, 7], [1, 3]]), sparse([[2, 4], [0, 1]]));
});
it('should perform element-wise modulus on sparse matrix and dense matrix', function() {
approx.deepEqual(mod(sparse([[-40, -31], [11, -23]]), matrix([[3, 7], [1, 3]])), sparse([[2, 4], [0, 1]]));
});
it('should perform element-wise modulus on sparse matrix and sparse matrix', function() {
approx.deepEqual(mod(sparse([[-40, -31], [11, -23]]), sparse([[3, 7], [1, 3]])), sparse([[2, 4], [0, 1]]));
});
});
it('should LaTeX mod', function () {
var expression = math.parse('mod(11,2)');
assert.equal(expression.toTex(), '\\left(11\\mod2\\right)');
});
});

View File

@ -1,9 +1,10 @@
// test round
var assert = require('assert'),
approx = require('../../../tools/approx'),
error = require('../../../lib/error/index'),
math = require('../../../index'),
bignumber = math.bignumber,
matrix = math.matrix,
sparse = math.sparse,
round = math.round;
describe('round', function() {
@ -83,6 +84,42 @@ describe('round', function() {
assert.deepEqual(round([1.7,2.3]), [2,2]);
assert.deepEqual(round(math.matrix([1.7,2.3])).valueOf(), [2, 2]);
});
describe('Array', function () {
it('should round array', function () {
assert.deepEqual(round([1.7, 2.3]), [2, 2]);
});
it('should round array and scalar', function () {
assert.deepEqual(round([1.7777, 2.3456], 3), [1.778, 2.346]);
assert.deepEqual(round(3.12385, [2, 3]), [3.12, 3.124]);
});
});
describe('DenseMatrix', function () {
it('should round dense matrix', function () {
assert.deepEqual(round(matrix([[1.7, 2.3], [8.987, -3.565]])), matrix([[2, 2], [9, -4]]));
});
it('should round dense matrix and scalar', function () {
assert.deepEqual(round(matrix([[1.7777, 2.3456],[-90.8272, 0]]), 3), matrix([[1.778, 2.346], [-90.827, 0]]));
assert.deepEqual(round(3.12385, matrix([[2, 3], [0, 2]])), matrix([[3.12, 3.124],[3, 3.12]]));
});
});
describe('SparseMatrix', function () {
it('should round sparse matrix', function () {
assert.deepEqual(round(sparse([[1.7, 0], [8.987, -3.565]])), sparse([[2, 0], [9, -4]]));
});
it('should round sparse matrix and scalar', function () {
assert.deepEqual(round(sparse([[1.7777, 2.3456],[-90.8272, 0]]), 3), sparse([[1.778, 2.346], [-90.827, 0]]));
assert.deepEqual(round(3.12385, sparse([[2, 3], [0, 2]])), matrix([[3.12, 3.124],[3, 3.12]]));
});
});
it('should LaTeX round', function () {
var expr1 = math.parse('round(1.1)');