All arithmetic functions not supporting BigNumbers downgrade BigNumbers to Numbers

This commit is contained in:
josdejong 2013-11-23 10:55:39 +01:00
parent 26c0332883
commit 4a99e03055
11 changed files with 132 additions and 10 deletions

View File

@ -4,9 +4,10 @@ https://github.com/josdejong/mathjs
## not yet released, version 0.16.0
- Implemented BigNumber support for arbitrary precision calculations,
added settings `number.defaultType` and `number.precision` to configure
- Implemented BigNumber support for arbitrary precision calculations.
Added settings `number.defaultType` and `number.precision` to configure
big numbers.
- Documentation is extended.
- Removed utility functions `isScalar`, `toScalar`, `isVector`, `toVector`
from `Matrix` and `Range`. Use `math.squeeze` and `math.size` instead.
- Implemented functions `get` and `set` on `Matrix`, for easier and faster

View File

@ -1,9 +1,11 @@
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = require('bignumber.js'),
collection = require('../../type/collection'),
isNumber = util.number.isNumber,
toNumber = util.number.toNumber,
isBoolean = util.boolean.isBoolean,
isInteger = util.number.isInteger,
isCollection = collection.isCollection;
@ -40,13 +42,33 @@ module.exports = function (math) {
return (a < 0) ? -a : a;
}
// TODO: implement BigNumber support for gcd
// evaluate gcd element wise
if (isCollection(a) || isCollection(b)) {
return collection.deepMap2(a, b, gcd);
}
// TODO: implement BigNumber support for gcd
// downgrade bignumbers to numbers
if (a instanceof BigNumber) {
a = toNumber(a);
if (isNumber(a)) {
return gcd(a, b);
}
else {
throw Error('Parameters in function gcd must be integer numbers.');
}
}
if (b instanceof BigNumber) {
b = toNumber(b);
if (isNumber(b)) {
return gcd(a, b);
}
else {
throw Error('Parameters in function gcd must be integer numbers.');
}
}
if (isBoolean(a)) {
return gcd(+a, b);
}

View File

@ -1,9 +1,11 @@
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = require('bignumber.js'),
collection = require('../../type/collection'),
isNumber = util.number.isNumber,
toNumber = util.number.toNumber,
isBoolean = util.boolean.isBoolean,
isInteger = util.number.isInteger,
isCollection = collection.isCollection;
@ -49,8 +51,6 @@ module.exports = function (math) {
return Math.abs(prod / a);
}
// TODO: implement BigNumber support for lcm
// evaluate lcm element wise
if (isCollection(a) || isCollection(b)) {
return collection.deepMap2(a, b, lcm);
@ -63,6 +63,28 @@ module.exports = function (math) {
return lcm(a, +b);
}
// TODO: implement BigNumber support for lcm
// downgrade bignumbers to numbers
if (a instanceof BigNumber) {
a = toNumber(a);
if (isNumber(a)) {
return lcm(a, b);
}
else {
throw Error('Parameters in function lcm must be integer numbers.');
}
}
if (b instanceof BigNumber) {
b = toNumber(b);
if (isNumber(b)) {
return lcm(a, b);
}
else {
throw Error('Parameters in function lcm must be integer numbers.');
}
}
throw new util.error.UnsupportedTypeError('lcm', a, b);
}

View File

@ -1,10 +1,12 @@
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = require('bignumber.js'),
Complex = require('../../type/Complex'),
collection = require('../../type/collection'),
isNumber = util.number.isNumber,
toNumber = util.number.toNumber,
isBoolean = util.boolean.isBoolean,
isComplex = Complex.isComplex,
isCollection = collection.isCollection;
@ -42,7 +44,11 @@ module.exports = function (math) {
);
}
// TODO: implement BigNumber support for log
if (x instanceof BigNumber) {
// TODO: implement BigNumber support for log
// downgrade to Number
return log(toNumber(x));
}
if (isCollection(x)) {
return collection.deepMap(x, log);

View File

@ -1,9 +1,11 @@
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = require('bignumber.js'),
Complex = require('../../type/Complex'),
collection = require('../../type/collection'),
toNumber = util.number.toNumber,
isNumber = util.number.isNumber,
isBoolean = util.boolean.isBoolean,
isComplex = Complex.isComplex,
@ -34,7 +36,11 @@ module.exports = function (math) {
}
}
// TODO: implement BigNumber support for log10
if (x instanceof BigNumber) {
// TODO: implement BigNumber support for log10
// downgrade to Number
return log10(toNumber(x));
}
if (isComplex(x)) {
return new Complex (

View File

@ -1,6 +1,9 @@
module.exports = function (math) {
var util = require('../../util/index'),
BigNumber = require('bignumber.js'),
toNumber = util.number.toNumber,
isNumber = util.number.isNumber,
isBoolean = util.boolean.isBoolean,
isInteger = util.number.isInteger;
@ -28,6 +31,28 @@ module.exports = function (math) {
return _xgcd(a, b);
}
// TODO: implement BigNumber support for xgcd
// downgrade bignumbers to numbers
if (a instanceof BigNumber) {
a = toNumber(a);
if (isNumber(a)) {
return xgcd(a, b);
}
else {
throw Error('Parameters in function xgcd must be integer numbers.');
}
}
if (b instanceof BigNumber) {
b = toNumber(b);
if (isNumber(b)) {
return xgcd(a, b);
}
else {
throw Error('Parameters in function xgcd must be integer numbers.');
}
}
if (isBoolean(a)) {
return xgcd(+a, b);
}
@ -38,8 +63,6 @@ module.exports = function (math) {
throw new util.error.UnsupportedTypeError('xgcd', a, b);
}
// TODO: implement BigNumber support for xgcd
// zero or one argument
throw new SyntaxError('Function xgcd expects two arguments');
};

View File

@ -44,6 +44,16 @@ describe('gcd', function() {
assert.deepEqual(2, gcd(-2, -6));
});
it('should calculate gcd for BigNumbers (downgrades to Number)', function() {
assert.equal(gcd(math.bignumber(12), math.bignumber(8)), 4);
assert.equal(gcd(math.bignumber(8), math.bignumber(12)), 4);
});
it('should calculate gcd for mixed BigNumbers to Numbers (downgrades to Number)', function() {
assert.equal(gcd(math.bignumber(12), 8), 4);
assert.equal(gcd(8, math.bignumber(12)), 4);
});
it('should find the greatest common divisor of booleans', function() {
assert.equal(gcd(true, true), 1);
assert.equal(gcd(true, false), 1);

View File

@ -34,6 +34,16 @@ describe('lcm', function() {
assert.equal(lcm(0, 0), 0);
});
it('should calculate lcm for BigNumbers (downgrades to Number)', function() {
assert.equal(lcm(math.bignumber(4), math.bignumber(6)), 12);
assert.equal(lcm(math.bignumber(4), math.bignumber(6)), 12);
});
it('should calculate lcm for mixed BigNumbers to Numbers (downgrades to Number)', function() {
assert.equal(lcm(math.bignumber(4), 6), 12);
assert.equal(lcm(4, math.bignumber(6)), 12);
});
it('should find the lowest common multiple of booleans', function() {
assert.equal(lcm(true, true), 1);
assert.equal(lcm(true, false), 0);

View File

@ -37,6 +37,12 @@ describe('log', function() {
assert.throws(function () {log(1, 2, 3)}, SyntaxError, 'Wrong number of arguments in function log (3 provided, 1-2 expected)');
});
it('should return the log of a bignumber', function() {
approx.deepEqual(log(math.bignumber(2)), 0.693147180559945);
approx.deepEqual(log(math.bignumber(3)), 1.098612288668110);
});
it('should return the log of a complex number', function() {
approx.deepEqual(log(math.i), complex('1.570796326794897i'));
approx.deepEqual(log(complex(0, -1)), complex('-1.570796326794897i'));

View File

@ -31,6 +31,12 @@ describe('log10', function() {
approx.deepEqual(log10(1000), 3);
});
it('should return the log of a bignumber', function() {
approx.deepEqual(log10(math.bignumber(2)), 0.301029995663981);
approx.deepEqual(log10(math.bignumber(3)), 0.477121254719662);
});
it('should throw an error if used with a wrong number of arguments', function() {
assert.throws(function () {log10()}, SyntaxError, 'Wrong number of arguments in function log10 (0 provided, 1 expected)');
assert.throws(function () {log10(1, 2)}, SyntaxError, 'Wrong number of arguments in function log10 (2 provided, 1 expected)');

View File

@ -36,6 +36,16 @@ describe('xgcd', function() {
assert.deepEqual([0, 0, 0], xgcd(0, 0));
});
it('should calculate xgcd for BigNumbers (downgrades to Number)', function() {
assert.deepEqual(xgcd(math.bignumber(65), math.bignumber(40)), [5, -3, 5]);
assert.deepEqual(xgcd(math.bignumber(65), math.bignumber(40)), [5, -3, 5]);
});
it('should calculate xgcd for mixed BigNumbers to Numbers (downgrades to Number)', function() {
assert.deepEqual(xgcd(math.bignumber(65), 40), [5, -3, 5]);
assert.deepEqual(xgcd(65, math.bignumber(40)), [5, -3, 5]);
});
it.skip ('should calculate xgcd for edge cases with negative values', function () {
assert.deepEqual([1, -2, 1], xgcd(2, 5));
assert.deepEqual([1, -2, -1], xgcd(2, -5));