Tested the functions. Made changes to the functions accordingly. Now puts more digits of pi into cosine to get the 'correct' values.

This commit is contained in:
Favian Contreras 2015-02-08 18:42:18 -08:00
parent efd946a081
commit 2de088cb0d
16 changed files with 382 additions and 146 deletions

View File

@ -12,7 +12,7 @@ module.exports = function (math) {
isComplex = Complex.isComplex,
isCollection = collection.isCollection,
bigArcCos = util.bignumber.acos;
bigArcCos = util.bignumber.arccos;
/**
* Calculate the inverse cosine of a value.

View File

@ -12,7 +12,7 @@ module.exports = function (math) {
isComplex = Complex.isComplex,
isCollection = collection.isCollection,
bigArcSin = util.bignumber.asin;
bigArcSin = util.bignumber.arcsin;
/**
* Calculate the inverse sine of a value.

View File

@ -12,7 +12,8 @@ module.exports = function (math) {
isComplex = Complex.isComplex,
isCollection = collection.isCollection,
bigArcTan = util.bignumber.arctan(x);
bigArcTan = util.bignumber.arctan;
/**
* Calculate the inverse tangent of a value.
*
@ -72,8 +73,6 @@ module.exports = function (math) {
}
if (x instanceof BigNumber) {
// TODO: implement BigNumber support
// downgrade to Number
return bigArcTan(x);
}

View File

@ -68,7 +68,7 @@ module.exports = function (math) {
}
if (x instanceof BigNumber) {
1 return bigCosh(x, 0);
return bigCosh(x, 0);
}
throw new math.error.UnsupportedTypeError('cosh', math['typeof'](x));

View File

@ -74,7 +74,7 @@ module.exports = function (math) {
}
if (x instanceof BigNumber) {
return bigCosh(x, 1);
return bigSinh(x, 1);
}
throw new math.error.UnsupportedTypeError('sinh', math['typeof'](x));

View File

@ -1,6 +1,6 @@
'use strict';
module.exports = function (math) {
module.exports = function (math, config) {
var util = require('../../util/index'),
BigNumber = math.type.BigNumber,

View File

@ -4,6 +4,7 @@ var BigNumber = require('decimal.js');
var isNumber = require('./number').isNumber;
var digits = require('./number').digits;
var memoize = require('./function').memoize;
var external = true;
/**
* Test whether value is a BigNumber
@ -486,110 +487,89 @@ function decCoefficientToBinaryString(x) {
/**
* Calculate the arc cosine of x
*
* acos(x) = pi/2 - asin(x)
* acos(x) = 2*atan(sqrt(1-x^2)/(1+x))
*
* @param {BigNumber} x
* @returns {BigNumber} arc cosine of x
*/
exports.arccos = function(x) {
var precision = x.constructor.precision;
var acos = exports.pi(precision + 4).div(2).minus(exports.arcsin(x));
exports.arccos = function (x) {
var Big = x.constructor;
var precision = Big.precision;
if (x.abs().gt(Big.ONE)) {
throw new Error('acos() only has non-complex values for |x| <= 1.');
}
if (x.eq(-1)) {
return exports.pi(precision);
}
acos.constructor.config({precision: precision});
return acos.toDP(precision);
Big.config({precision: precision + 4});
var acos = exports.arctan(Big.ONE.minus(x.times(x)).sqrt()
.div(x.plus(Big.ONE))).times(2);
Big.config({precision: precision});
return acos.toDP(precision - 1);
};
/**
* Calculate the arc sine of x using Newton's method
*
* f(x) = sin(x) = N => f(x) = sin(x) - N
* f'(x) = cos(x)
*
* Thus we solve each step as follows:
* x_(i+1) = x_i - (sin(x_i) - N)/cos(x_i)
* Calculate the arc sine of x
*
* @param {BigNumber} x
* @returns {BigNumber} arc sine of x
*/
exports.arcsin = function(x) {
exports.arcsin = function (x) {
var Big = x.constructor;
if (x.isNaN()) {
return new x.constructor(NaN);
return new Big(NaN);
}
if (x.isZero()) {
return new x.constructor(0);
return new Big(0);
}
if (x.gt(1)) {
throw new Error('arcsin() only has non-complex values for |x| <= 1.');
var absX = x.abs();
if (absX.gt(1)) {
throw new Error('asin() only has non-complex values for |x| <= 1.');
}
var Big;
var oldPrecision = x.constructor.precision;
// Get x to ~0.5
if (x.gt('0.864')) {
Big = x.constructor;
Big.config({precision: oldPrecision + 2});
var precision = Big.precision;
// Get x below 0.58
if (absX.gt('0.8')) {
Big.config({precision: precision + 4});
// arcsin(x) = sign(x)*(Pi/2 - arcsin(sqrt(1 - x^2)))
var sign = x.s;
var halfPi = exports.pi(oldPrecision + 2).div(2);
x = halfPi.minus(exports.arcsin(Big.ONE.minus(x.times(x))));
var halfPi = exports.pi(precision + 4).div(2);
x = halfPi.minus(exports.arcsin(Big.ONE.minus(x.times(x)).sqrt()));
x.s = sign;
Big.config({precision: oldPrecision});
return x.toDP(oldPrecision - 1);
x.constructor = Big;
Big.config({precision: precision});
return x.toDP(precision - 1);
}
if (x.gt('0.505')) {
Big = x.constructor;
Big.config({precision: oldPrecision + 8});
var wasReduced;
if (wasReduced = absX.gt('0.58')) {
Big.config({precision: precision + 8});
// arcsin(x) = 2*arcsin(x / (sqrt(2)*sqrt(sqrt(1 - x^2) + 1)))
x = x.div(new Big(2).sqrt().times(Big.ONE.minus(x.times(x)).sqrt()
.plus(Big.ONE).sqrt()));
Big.config({precision: oldPrecision});
return new Big(2).times(exports.arcsin(x));
Big.config({precision: precision});
}
// Calibration variables, adjusted from MAPM.
var tolerance = -(oldPrecision + 4);
var maxp = oldPrecision + 8 - x.e;
var localPrecision = 25 - x.e;
var maxIter = Math.max(Math.log(oldPrecision + 2) * 1.442695 | 0 + 5, 5);
// Avoid overhead of Newton's Method if feasible
var ret = (precision <= 60 || ((x.dp() <= Math.log(precision)) && x.lt('0.05')))
? arcsin_taylor(x, precision)
: arcsin_newton(x, precision);
Big = BigNumber.constructor({precision: oldPrecision});
var curr = new Big(Math.asin(x.toNumber()) + '');
var i = 0;
var tmp0, tmp1, tmp2;
do {
tmp0 = exports.cos_sin(curr, localPrecision, 1);
tmp1 = sin_cos_swap(tmp0);
if (!tmp0.isZero()) {
tmp0.s = curr.s;
}
tmp2 = tmp0.minus(x).div(tmp1);
curr = curr.minus(tmp2);
localPrecision = Math.min(2*localPrecision, maxp);
Big.config({precision: localPrecision});
} while ((2*tmp2.e >= tolerance) && !tmp2.isZero() && (++i <= maxIter))
if (i == maxIter) {
throw new Error('arcsin() failed to converge to the requested accuracy.' +
'Try with a higher precision.');
if (wasReduced) {
return ret.times(2);
}
Big.config({precision: oldPrecision});
return curr.toDP(oldPrecision - 1);
return ret;
};
/**
* Calculate the arc tangent of x using a variety of methods.
* Inspired by MAPM and Michael C. Ring.
* Calculate the arc tangent of x
*
* @param {BigNumber} x
* @returns {BigNumber} arc tangent of x
@ -602,22 +582,34 @@ exports.arctan = function (x) {
if (x.isZero()) {
return new Big(0);
}
if (x.e <= -4) {
return arctan_taylor(x);
}
var precision = Big.precision;
if (x.e >= 4) {
if (!x.isFinite()) {
var halfPi = exports.pi(precision + 2).div(2).toDP(precision - 1);
halfPi.s = x.s;
return halfPi;
}
var absX = x.abs();
if (absX.lte('0.875')) {
Big.config({precision: precision + 4});
// arctan(x) = (PI / 2) - arctan(1 / |x|)
var ret = arctan_taylor(x);
ret.constructor = Big;
Big.config({precision: precision});
return ret.toDP(Big.precision - 1);
}
if (absX.gte('1.143')) {
Big.config({precision: precision + 4});
// arctan(x) = sign(x)*((PI / 2) - arctan(1 / |x|))
var halfPi = exports.pi(precision + 4).div(2);
var ret = halfPi.minus(arctan_taylor(Big.ONE.div(x.abs())));
var ret = halfPi.minus(arctan_taylor(Big.ONE.div(absX)));
ret.s = x.s;
ret.constructor = Big;
Big.config({precision: precision});
ret.constructor.config({precision: precision});
console.log(Big == ret.consructor);
return ret.toDP(Big.precision - 1);
}
@ -643,26 +635,33 @@ exports.arctan = function (x) {
* @returns {BigNumber} sine or cosine of x
*/
exports.cos_sin = function (x, precision, mode) {
var Big;
if (x.isNaN() || !x.isFinite()) {
var Big = BigNumber.constructor({precision: precision});
Big = BigNumber.constructor({precision: precision});
return new Big(NaN);
}
// Avoid changing the original value
Big = BigNumber.constructor({precision: x.constructor.precision});
var y = new Big(x);
y.constructor = Big; // Not sure why I have to do this...
// sin(-x) == -sin(x), cos(-x) == cos(x)
var isNeg = x.isNegative();
var isNeg = y.isNegative();
if (isNeg) {
x.s = -x.s;
y.s = -y.s;
}
var y = reduceToPeriod(x, precision, mode); // Make this destructive
y = reduceToPeriod(y, precision, mode); // Make this destructive
if (y[1]) {
return y[0];
}
var ret;
y = y[0];
var Big = y.constructor;
Big = y.constructor;
if (mode) {
var ret = cos_sin_taylor(y.div(3125), mode);
ret = cos_sin_taylor(y.div(3125), mode);
Big.config({precision: Math.min(Big.precision, precision + 15)});
var five = new Big(5);
@ -690,7 +689,7 @@ exports.cos_sin = function (x, precision, mode) {
loops = 4;
}
var ret = cos_sin_taylor(y.div(div_factor), mode);
ret = cos_sin_taylor(y.div(div_factor), mode);
Big.config({precision: Math.min(Big.precision, precision + 8)});
var eight = new Big(8);
@ -715,14 +714,33 @@ exports.cos_sin = function (x, precision, mode) {
* @returns {BigNumber} tangent of x
*/
exports.tan = function (x, precision) {
var sin = exports.sin(x, precision, 1);
var cos = sin_cos_swap(sin);
var Big = BigNumber.constructor({precision: precision});
if (x.isNaN()) {
return new Big(NaN);
}
var y = reduceToPeriod(x, precision, 1)[0];
var pi = exports.pi(precision + 4);
if (y.abs().eq(pi.toDP(precision))) {
return new Big(Infinity);
}
var sin = exports.cos_sin(y, precision + 4, 1);
var cos = sinToCos(sin);
// Make sure sign for cosine is correct
if (y.eq(x)) {
if (y.gt(pi.div(2).toDP(precision))) {
cos.s = -cos.s;
}
} else if (pi.minus(y.abs()).gt(pi.div(2))) {
cos.s = -cos.s;
}
sin.constructor.config({precision: precision + 4});
var tan = sin.div(cos);
tan.constructor.config({precision: precision});
return tan;
return new Big(tan.toPrecision(precision));
};
/**
@ -743,16 +761,19 @@ exports.cosh_sinh = function (x, mode) {
if (x.isNaN()) {
return new Big(NaN);
}
if (!x.isFinite()) {
return new Big((mode) ? x : Infinity);
}
var precision = Big.precision;
Big.config({precision: precision + 4});
var y = x.exp();
y = (mode) ? y.plus(Big.ONE.div(y)) : y.minus(Big.ONE.div(y));
y = (mode) ? y.minus(Big.ONE.div(y)) : y.plus(Big.ONE.div(y));
y = y.div(2);
Big.config({precision: precision});
return y.toDP(precision - 1);
return new Big(y.toPrecision(precision));
};
/**
@ -770,6 +791,9 @@ exports.tanh = function (x) {
if (x.isNaN()) {
return new Big(NaN);
}
if (!x.isFinite()) {
return new Big(x.isNegative() ? -1 : 1);
}
var precision = Big.precision;
Big.config({precision: precision + 4});
@ -783,6 +807,91 @@ exports.tanh = function (x) {
return ret.toDP(precision - 1);
};
/**
* Calculate the arc sine of x using Newton's method
*
* f(x) = sin(x) = N => f(x) = sin(x) - N
* f'(x) = cos(x)
*
* Thus we solve each step as follows:
* x_(i+1) = x_i - (sin(x_i) - N)/cos(x_i)
*
* @param {BigNumber} x
* @param {Number} oldPrecision
* @returns {BigNumber} arc sine of x
*/
function arcsin_newton(x, oldPrecision) {
// Calibration variables, adjusted from MAPM
var tolerance = -(oldPrecision + 4);
var maxp = oldPrecision + 8 - x.e;
var localPrecision = 25 - x.e;
var maxIter = Math.max(Math.log(oldPrecision + 2) * 1.442695 | 0 + 5, 5);
var Big = BigNumber.constructor({precision: oldPrecision});
var curr = new Big(Math.asin(x.toNumber()) + '');
var i = 0;
do {
var tmp0 = exports.cos_sin(curr, localPrecision, 1);
var tmp1 = sinToCos(tmp0);
if (!tmp0.isZero()) {
tmp0.s = curr.s;
}
var tmp2 = tmp0.minus(x).div(tmp1);
curr = curr.minus(tmp2);
localPrecision = Math.min(2*localPrecision, maxp);
curr.constructor.config({precision: localPrecision});
} while ((2*tmp2.e >= tolerance) && !tmp2.isZero() && (++i <= maxIter))
if (i == maxIter) {
throw new Error('asin() failed to converge to the requested accuracy.' +
'Try with a higher precision.');
}
curr.constructor.config({precision: oldPrecision});
return curr.toDP(oldPrecision - 1);
}
/**
* Calculate the arc sine of x
*
* arcsin(x) = x + (1/2)*x^3/3 + (3/8)*x^5/5 + (15/48)*x^7/7 ...
* = x + (1/2)*x^2*x^1/3 + [(1*3)/(2*4)]*x^2*x^3/5 + [(1*3*5)/(2*4*6)]*x^2*x^5/7 ...
*
* @param {BigNumber} x
* @param {Number} precision
* @returns {BigNumber} arc sine of x
*/
function arcsin_taylor(x, precision) {
var Big = x.constructor;
Big.config({precision: precision + Math.log(precision) | 0 + 4});
var one = new Big(1);
var y = x;
var yPrev = NaN;
var x2 = x.times(x);
var polyNum = x;
var constNum = new Big(one);
var constDen = new Big(one);
var bigK = new Big(one);
for (var k = 3; !y.equals(yPrev); k += 2) {
polyNum = polyNum.times(x2);
constNum = constNum.times(bigK);
constDen = constDen.times(bigK.plus(one));
yPrev = y;
bigK = new Big(k);
y = y.plus(polyNum.times(constNum).div(bigK.times(constDen)));
}
Big.config({precision: precision});
return y.toDP(precision - 1);
}
/**
* Calculate the arc tangent of x using a Taylor expansion
*
@ -855,11 +964,19 @@ function cos_sin_taylor(x, mode) {
*/
function reduceToPeriod(x, precision, mode) {
var Big = x.constructor;
var xPrecision = Big.precision
var prec_plus_guard_digits = precision + (Math.log(precision) | 0) + 3;
Big.config({precision: prec_plus_guard_digits});
var y;
var pi = exports.pi(prec_plus_guard_digits + 2);
var tau = exports.tau(prec_plus_guard_digits);
if (x.abs().lte(pi)) {
y = new Big(x);
y.constructor = BigNumber.constructor({precision: prec_plus_guard_digits});
Big.config({precision: xPrecision});
return [y, false];
}
// Catch if input is tau multiple using pi's precision
if (x.div(pi.toDP(x.dp(), 1)).toNumber() % 2 == 0) {
@ -867,9 +984,9 @@ function reduceToPeriod(x, precision, mode) {
return [new Big(mode ^ 1), true];
}
var y = x.mod(tau);
y = x.mod(tau);
y.constructor = BigNumber.constructor({precision: prec_plus_guard_digits});
Big.config({precision: precision});
Big.config({precision: xPrecision});
// Catch if tau multiple with tau's precision
if (y.toDP(x.dp(), 1).isZero()) {
@ -891,24 +1008,22 @@ function reduceToPeriod(x, precision, mode) {
}
/**
* Convert between sine and cosine values
* Convert from cosine to sine
*
* cos(x) = sqrt(1 - sin(x)^2)
* |cos(x)| = sqrt(1 - sin(x)^2)
*
* sin(x) = sqrt(1 - cos(x)^2)
*
* @param {BigNumber} x
* @returns {BigNumber} sine as cosine, or cosine as sine
* @param {BigNumber} sine of x
* @returns {BigNumber} sine as cosine
*/
function sin_cos_swap(x) {
var Big = x.constructor;
function sinToCos(sinVal) {
var Big = sinVal.constructor;
var precision = Big.precision;
Big.config({precision: precision + 4});
var ret = Big.ONE.minus(x.times(x)).sqrt();
var ret = Big.ONE.minus(sinVal.times(sinVal)).sqrt();
Big.config({precision: precision});
return ret;
return ret.toDP(precision - 1);
}

View File

@ -7,7 +7,9 @@ var assert = require('assert'),
cos = math.cos,
complex = math.complex,
matrix = math.matrix,
unit = math.unit;
unit = math.unit,
bigmath = math.create({number: 'bignumber', precision: 20}),
Big = bigmath.bignumber;
describe('acos', function() {
it('should return the arccos of a boolean', function () {
@ -27,8 +29,16 @@ describe('acos', function() {
approx.equal(acos(1) / pi, 0);
});
it('should return the arccos of a bignumber (downgrades to number)', function() {
approx.equal(acos(math.bignumber(-1)), pi);
it('should return the arccos of a bignumber', function() {
assert.deepEqual(acos(Big(-1)).toString(), bigmath.pi.toString());
assert.deepEqual(acos(Big(-0.5)), Big('2.0943951023931954923'));
assert.deepEqual(acos(Big(0)), Big('1.5707963267948966192'));
assert.deepEqual(acos(Big(0.5)), Big('1.0471975511965977462'));
assert.deepEqual(acos(Big(1)), Big(0));
// Hit Newton's method case
bigmath.config({precision: 61});
assert.deepEqual(acos(Big('0.00000001')), Big('1.570796316794896619231321524973084775431910533020886243820359'));
});
it('should be the inverse function of cos', function() {
@ -39,6 +49,15 @@ describe('acos', function() {
approx.equal(acos(cos(2)), 2);
});
it('should be the inverse function of bignumber cos', function() {
bigmath.config({precision: 20});
assert.deepEqual(acos(bigmath.cos(Big(-1))).toString(), '1');
assert.ok(acos(bigmath.cos(Big(0))).isZero());
assert.deepEqual(acos(bigmath.cos(Big(0.1))).toString(), '0.1');
assert.deepEqual(acos(bigmath.cos(Big(0.5))).toString(), '0.5');
assert.deepEqual(acos(bigmath.cos(Big(2))).toString(), '2');
});
it('should return the arccos of a complex number', function() {
approx.deepEqual(acos(complex('2+3i')), complex(1.00014354247380, -1.98338702991654));
approx.deepEqual(acos(complex('2-3i')), complex(1.00014354247380, 1.98338702991654));
@ -71,4 +90,4 @@ describe('acos', function() {
assert.throws(function () {acos(1, 2)}, error.ArgumentsError);
});
});
});

View File

@ -7,7 +7,9 @@ var assert = require('assert'),
matrix = math.matrix,
unit = math.unit,
asin = math.asin,
sin = math.sin;
sin = math.sin,
bigmath = math.create({number: 'bignumber', precision: 20}),
Big = bigmath.bignumber;
describe('asin', function() {
it('should return the arcsin of a boolean', function () {
@ -27,8 +29,18 @@ describe('asin', function() {
approx.equal(asin(1) / pi, 0.5);
});
it('should return the arcsin of a bignumber (downgrades to number)', function() {
approx.equal(asin(math.bignumber(-1)), -pi / 2);
it('should return the arcsin of a bignumber', function() {
assert.deepEqual(asin(Big(-1)), Big('-1.5707963267948966192'));
assert.deepEqual(asin(Big(-0.581)), Big('-0.6199567994522537004'));
assert.deepEqual(asin(Big(-0.5)), Big('-0.5235987755982988731'));
assert.deepEqual(asin(Big(0)), Big(0));
assert.deepEqual(asin(Big(0.5)), Big('0.5235987755982988731'));
assert.deepEqual(asin(Big(0.581)), Big('0.6199567994522537004'));
assert.deepEqual(asin(Big(1)), Big('1.5707963267948966192'));
// Hit Newton's method case
bigmath.config({precision: 61});
assert.deepEqual(asin(Big('0.00000001')), Big('1.0000000000000000166666666666666674166666666666667113e-8'));
});
it('should be the inverse function of sin', function() {
@ -39,6 +51,27 @@ describe('asin', function() {
approx.equal(asin(sin(2)), 1.14159265358979);
});
it('should be the inverse function of bignumber sin', function() {
// More Newton's method test cases
assert.deepEqual(asin(bigmath.sin(Big(-2))).toString(), '-1.141592653589793238462643383279502884197169399375105820974945');
assert.deepEqual(asin(bigmath.sin(Big(-0.5))).toString(), '-0.5');
assert.deepEqual(asin(bigmath.sin(Big(-0.1))).toString(), '-0.1');
assert.deepEqual(asin(bigmath.sin(Big(0.1))).toString(), '0.1');
assert.deepEqual(asin(bigmath.sin(Big(0.5))).toString(), '0.5');
assert.deepEqual(asin(bigmath.sin(Big(2))).toString(), '1.141592653589793238462643383279502884197169399375105820974945');
bigmath.config({precision: 20});
// Full decimal Taylor test cases
/* sin(-1) = -0.8414709848078965067
asin(-0.8414709848078965067) = -1.00000000000000000008 => (rounding up) -1.0000000000000000001
assert.deepEqual(asin(bigmath.sin(Big(-1))), Big('-1')); */
assert.ok(asin(bigmath.sin(Big(0))).isZero());
assert.deepEqual(asin(bigmath.sin(Big(0.1))).toString(), '0.1');
assert.deepEqual(asin(bigmath.sin(Big(0.5))).toString(), '0.5');
assert.deepEqual(asin(bigmath.sin(Big(2))).toString(), '1.1415926535897932385');
});
it('should return the arcsin of a complex number', function() {
var re = 0.570652784321099;
var im = 1.983387029916536;
@ -76,4 +109,4 @@ describe('asin', function() {
assert.throws(function () {asin(1, 2)}, error.ArgumentsError);
});
});
});

View File

@ -7,7 +7,9 @@ var assert = require('assert'),
matrix = math.matrix,
unit = math.unit,
atan = math.atan,
tan = math.tan;
tan = math.tan,
bigmath = math.create({number: 'bignumber', precision: 20}),
Big = bigmath.bignumber;
describe('atan', function() {
it('should return the arctan of a boolean', function () {
@ -27,8 +29,16 @@ describe('atan', function() {
approx.equal(atan(1) / pi, 0.25);
});
it('should return the arctan of a bignumber (downgrades to number)', function() {
approx.equal(atan(math.bignumber(1)), pi / 4);
it('should return the arctan of a bignumber', function() {
assert.deepEqual(atan(Big(-1)), Big('-0.7853981633974483096'));
assert.deepEqual(atan(Big(-0.5)), Big('-0.4636476090008061162'));
assert.deepEqual(atan(Big(0)), Big(0));
assert.deepEqual(atan(Big(0.5)), Big('0.4636476090008061162'));
assert.deepEqual(atan(Big(1)), Big('0.7853981633974483096'));
// Hit Newton's method case
bigmath.config({precision: 61});
assert.deepEqual(atan(Big(0.90)).toString(), '0.732815101786506591640792072734280251985755679358256086310506');
});
it('should be the inverse function of tan', function() {
@ -39,6 +49,16 @@ describe('atan', function() {
approx.equal(atan(tan(2)), -1.14159265358979);
});
it('should be the inverse function of bignumber tan', function() {
bigmath.config({precision: 20});
assert.deepEqual(atan(bigmath.tan(Big(-1))).toString(), '-1');
assert.ok(atan(bigmath.tan(Big(0))).isZero());
assert.deepEqual(atan(bigmath.tan(Big(0.1))).toString(), '0.1');
assert.deepEqual(atan(bigmath.tan(Big(0.5))).toString(), '0.5');
assert.deepEqual(atan(bigmath.tan(Big(2))).toString(), '-1.1415926535897932385');
assert.deepEqual(atan(bigmath.tan(bigmath.pi.div(2))).toString(), '-1.5707963267948966192');
});
it('should return the arctan of a complex number', function() {
var re = 1.409921049596575,
im = 0.229072682968539;
@ -72,4 +92,4 @@ describe('atan', function() {
assert.throws(function () {atan(1, 2)}, error.ArgumentsError);
});
});
});

View File

@ -6,7 +6,10 @@ var assert = require('assert'),
complex = math.complex,
matrix = math.matrix,
unit = math.unit,
cos = math.cos;
cos = math.cos,
bigmath = math.create({number: 'bignumber', precision: 15}),
biggermath = math.create({precision: 238});
describe('cos', function() {
it('should return the cosine of a boolean', function () {
@ -33,8 +36,7 @@ describe('cos', function() {
});
it('should return the cosine of a bignumber', function() {
var bigmath = math.create({number: 'bignumber', precision: 238});
assert.deepEqual(bigmath.cos(bigmath.bignumber(0)), bigmath.bignumber(1));
assert.deepEqual(bigmath.cos(biggermath.bignumber(0)).toString(), '1');
// 103.64 % tau = 3.109... <- pretty close to the pi boundary
var result_val = '-0.99947004918247698171247470962484532559534008595265991588' +
@ -42,33 +44,31 @@ describe('cos', function() {
'80857263937361947475191126604630777331941809888320749410' +
'59494006339537812110786663367929884637840572887762249921' +
'8425619255481';
var cos_val = bigmath.cos(bigmath.bignumber(103.64));
var cos_val = biggermath.cos(biggermath.bignumber(103.64));
assert.equal(cos_val.constructor.precision, 238);
assert.deepEqual(cos_val.toString(), result_val);
cos_val = bigmath.cos(bigmath.bignumber(-103.64));
cos_val = biggermath.cos(biggermath.bignumber(-103.64));
assert.equal(cos_val.constructor.precision, 238);
assert.deepEqual(cos_val.toString(), result_val);
bigmath.config({precision: 15});
var bigPi = bigmath.pi;
result_val = bigmath.SQRT2.div(2).toString();
assert.deepEqual(bigmath.cos(bigPi.div(4)).toString(), result_val);
assert.ok(bigmath.cos(bigPi.div(2)).isZero());
assert.deepEqual(bigmath.cos(bigPi).toString(), '-1');
assert.ok(bigmath.cos(bigPi.times(3).div(2)).isZero());
assert.deepEqual(bigmath.cos(bigPi.times(2)).toString(), '1');
assert.deepEqual(bigmath.cos(bigmath.tau).toString(), '1');
assert.deepEqual(bigmath.cos(bigmath.tau.times(2)).toString(), '1');
/* If we ever decide to pass in more digits of pi, uncomment these.
/* Pass in more digits of pi! */
biggermath.config({number: 'bignumber', precision: 17});
bigPi = biggermath.pi;
assert.deepEqual(bigmath.cos(bigPi.times(3).div(4)).toString(), '-'+result_val);
assert.deepEqual(bigmath.cos(bigPi.times(5).div(4)).toString(), '-'+result_val);
assert.deepEqual(bigmath.cos(bigPi.times(7).div(4)).toString(), result_val);
*/
});
it('should return the cosine of a complex number', function() {

View File

@ -26,8 +26,18 @@ describe('cosh', function() {
approx.equal(cosh(3), 10.067661995778);
});
it('should return the cosh of a bignumber (downgrades to number)', function() {
approx.equal(cosh(math.bignumber(1)), 1.5430806348152);
it('should return the cosh of a bignumber', function() {
var bigmath = math.create({number: 'bignumber', precision: 20});
var Big = bigmath.bignumber;
assert.deepEqual(cosh(Big(-3)), Big('10.067661995777765842'));
assert.deepEqual(cosh(Big(-2)), Big('3.7621956910836314596'));
assert.deepEqual(cosh(Big(-1)), Big('1.5430806348152437785'));
assert.deepEqual(cosh(Big(0)), Big(1));
assert.deepEqual(cosh(Big(1)), Big('1.5430806348152437785'));
assert.deepEqual(cosh(Big(2)), Big('3.7621956910836314596'));
assert.deepEqual(cosh(Big(3)), Big('10.067661995777765842'));
assert.deepEqual(cosh(bigmath.pi).toString(), '11.591953275521520628');
});
it('should return the cosh of a complex number', function() {

View File

@ -6,7 +6,8 @@ var assert = require('assert'),
complex = math.complex,
matrix = math.matrix,
unit = math.unit,
sin = math.sin;
sin = math.sin,
bigmath = math.create({precision: 242});
describe('sin', function() {
it('should return the sine of a boolean', function () {
@ -32,7 +33,6 @@ describe('sin', function() {
});
it('should return the sine of a bignumber', function() {
var bigmath = math.create({number: 'bignumber', precision: 242});
assert.ok(bigmath.sin(bigmath.bignumber(0)).isZero());
// 103.64 % tau = 3.109... <- pretty close to the pi boundary
@ -48,7 +48,7 @@ describe('sin', function() {
'3071480438329880550139583951234188873226108092477936610585549' +
'3575835362891900420559398509489530577719840860106717522689249' +
'6061212602629134186583352145117086874446046421403346033616');
bigmath.config({precision: 15});
bigmath.config({number: 'bignumber', precision: 15});
var bigPi = bigmath.pi;
result_val = bigmath.SQRT2.div(2).toString();

View File

@ -30,8 +30,18 @@ describe('sinh', function() {
assert.equal(sinh(1e-50), 1e-50);
})
it('should return the sinh of a bignumber (downgrades to number)', function() {
approx.equal(sinh(math.bignumber(1)), 1.1752011936438014);
it('should return the sinh of a bignumber', function() {
var bigmath = math.create({number: 'bignumber', precision: 20});
var Big = bigmath.bignumber;
assert.deepEqual(sinh(Big(-1)), Big('-1.1752011936438014569'));
assert.deepEqual(sinh(Big(0)), Big(0));
assert.deepEqual(sinh(bigmath.pi).toString(), '11.548739357257748378');
assert.deepEqual(sinh(Big(1)), Big('1.1752011936438014569'));
assert.deepEqual(sinh(Big(-1e-10)), Big(-1e-10));
bigmath.config({precision: 50});
assert.deepEqual(sinh(Big(1e-50)), Big(1e-50));
});
it('should return the sinh of a complex number', function() {

View File

@ -33,8 +33,28 @@ describe('tan', function() {
approx.equal(tan(pi*8/4), 0);
});
it('should return the tangent of a bignumber (downgrades to number)', function() {
approx.equal(tan(math.bignumber(1)), 1.55740772465490);
it('should return the tangent of a bignumber', function() {
var piBigmath = math.create({number: 'bignumber', precision: 24});
var bigPi = piBigmath.pi;
var bigTau = piBigmath.tau;
var bigmath = math.create({precision: 20});
assert.ok(bigmath.tan(bigmath.bignumber(0)).isZero());
assert.deepEqual(bigmath.tan(bigmath.bignumber(-1)).toString(), '-1.5574077246549022305');
assert.deepEqual(bigmath.tan(bigPi.div(8)).toString(), '0.4142135623730950488');
assert.deepEqual(bigmath.tan(bigPi.div(4)).toString(), '1');
assert.ok(!bigmath.tan(bigPi.div(2)).isFinite());
assert.deepEqual(bigmath.tan(bigPi.times(3).div(4)).toString(), '-1');
assert.ok(bigmath.tan(bigPi).isZero());
assert.deepEqual(bigmath.tan(bigPi.times(5).div(4)).toString(), '1');
assert.ok(!bigmath.tan(bigPi.times(3).div(2)).isFinite());
assert.deepEqual(bigmath.tan(bigPi.times(7).div(4)).toString(), '-1');
assert.ok(bigmath.tan(bigPi.times(2)).isZero());
assert.ok(bigmath.tan(bigPi.times(4)).isZero());
assert.ok(bigmath.tan(bigTau).isZero());
assert.ok(bigmath.tan(bigTau.times(2)).isZero());
});
it('should return the tangent of a complex number', function() {
@ -77,4 +97,4 @@ describe('tan', function() {
assert.throws(function () {tan(1, 2)}, error.ArgumentsError);
});
});
});

View File

@ -26,8 +26,18 @@ describe('tanh', function() {
approx.equal(tanh(3), 0.99505475368673);
});
it('should return the tanh of a bignumber (downgrades to number)', function() {
approx.equal(tanh(math.bignumber(1)), 0.76159415595576);
it('should return the tanh of a bignumber', function() {
var bigmath = math.create({number: 'bignumber', precision: 20});
var Big = bigmath.bignumber;
assert.deepEqual(tanh(Big(-3)), Big('-0.9950547536867304513'));
assert.deepEqual(tanh(Big(-2)), Big('-0.9640275800758168839'));
assert.deepEqual(tanh(Big(-1)), Big('-0.7615941559557648881'));
assert.deepEqual(tanh(Big(0)), Big(0));
assert.deepEqual(tanh(Big(1)), Big('0.7615941559557648881'));
assert.deepEqual(tanh(Big(2)), Big('0.9640275800758168839'));
assert.deepEqual(tanh(Big(3)), Big('0.9950547536867304513'));
assert.deepEqual(tanh(bigmath.pi).toString(), '0.9962720762207499443');
});
it('should return the tanh of a complex number', function() {