diff --git a/lib/function/trigonometry/acosh.js b/lib/function/trigonometry/acosh.js new file mode 100644 index 000000000..2a207c378 --- /dev/null +++ b/lib/function/trigonometry/acosh.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAcosh = util.bignumber.acosh_asinh_asech_acsch; + + /** + * Calculate the hyperbolic arccos of a value, + * defined as `acosh(x) = ln(x + sqrt(x^2 - 1))`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.acosh(x) + * + * Examples: + * + * math.acosh(1.5); // returns 0.962423650119206 + * + * See also: + * + * asinh, atanh + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arccosine of x + */ + math.acosh = function acosh(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('acosh', arguments.length, 1); + } + + if (isNumber(x)) { + return Math.log(x + Math.sqrt(x*x - 1)); + } + + if (isComplex(x)) { + return new Complex( + Math.log(x.re + Math.sqrt(x.re*x.re - 1)), + Math.log(x.im + Math.sqrt(x.im + 1)*Math.sqrt(x.im - 1)) + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function acosh is no angle'); + } + return acosh(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, acosh); + } + + if (isBoolean(x) || x === null) { + return 0; + } + + if (x instanceof BigNumber) { + return bigAcosh(x, 0, false); + } + + throw new math.error.UnsupportedTypeError('acosh', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/acoth.js b/lib/function/trigonometry/acoth.js new file mode 100644 index 000000000..cb7623e05 --- /dev/null +++ b/lib/function/trigonometry/acoth.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAcoth = util.bignumber.atanh_acoth; + + /** + * Calculate the hyperbolic arccotangent of a value, + * defined as `acoth(x) = 2 / ln((1 + x)/(1 - x))`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.acoth(x) + * + * Examples: + * + * math.acoth(0.5); // returns 0.4812118250596 + * + * See also: + * + * acsch, asech + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arccotangent of x + */ + math.acoth = function acoth(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('acoth', arguments.length, 1); + } + + if (isNumber(x)) { + return 2 / Math.log((1 + x)/(1 - x)); + } + + if (isComplex(x)) { + return new Complex( + 2 / Math.log((1 + x.re)/(1 - x.re)), + 2 / (Math.log(1 + x.im) - Math.log(1 - x.im)) + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function acoth is no angle'); + } + return acoth(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, acoth); + } + + if (isBoolean(x) || x === null) { + return (x) ? Infinity : 0; + } + + if (x instanceof BigNumber) { + return bigAcoth(x, true); + } + + throw new math.error.UnsupportedTypeError('acoth', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/acsch.js b/lib/function/trigonometry/acsch.js new file mode 100644 index 000000000..f5b765c66 --- /dev/null +++ b/lib/function/trigonometry/acsch.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAcsch = util.bignumber.acosh_asinh_asech_acsch; + + /** + * Calculate the hyperbolic arccosecant of a value, + * defined as `acsch(x) = 1 / ln(x + sqrt(x^2 + 1))`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.acsch(x) + * + * Examples: + * + * math.acsch(0.5); // returns 0.4812118250596 + * + * See also: + * + * asech, acoth + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arccosecant of x + */ + math.acsch = function acsch(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('acsch', arguments.length, 1); + } + + if (isNumber(x)) { + return 1 / Math.log(x + Math.sqrt(x*x + 1)); + } + + if (isComplex(x)) { + return new Complex( + 1 / Math.log(x.re + Math.sqrt(x.re*x.re + 1)), + 1 / Math.log(x.im + Math.sqrt(x.im*x.im + 1)) + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function acsch is no angle'); + } + return acsch(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, acsch); + } + + if (isBoolean(x) || x === null) { + return (x) ? Math.log(1 + Math.SQRT1_2) : Infinity; + } + + if (x instanceof BigNumber) { + return bigAcsch(x, 1, true); + } + + throw new math.error.UnsupportedTypeError('acsch', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/asech.js b/lib/function/trigonometry/asech.js new file mode 100644 index 000000000..577fbeb20 --- /dev/null +++ b/lib/function/trigonometry/asech.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAsech = util.bignumber.acosh_asinh_asech_acsch; + + /** + * Calculate the hyperbolic arccos of a value, + * defined as `asech(x) = 1 / ln(x + sqrt(x^2 - 1))`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.asech(x) + * + * Examples: + * + * math.asech(0.5); // returns 0.4812118250596 + * + * See also: + * + * acsch, acoth + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arcsecant of x + */ + math.asech = function asech(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('asech', arguments.length, 1); + } + + if (isNumber(x)) { + return 1 / Math.log(x + Math.sqrt(x*x - 1)); + } + + if (isComplex(x)) { + return new Complex( + 1 / Math.log(x.re + Math.sqrt(x.re*x.re - 1)), + 1 / Math.log(x.im + Math.sqrt(x.im + 1)*Math.sqrt(x.im - 1)) + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function asech is no angle'); + } + return asech(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, asech); + } + + if (isBoolean(x) || x === null) { + return (x) ? 0 : Infinity; + } + + if (x instanceof BigNumber) { + return bigAsech(x, 0, true); + } + + throw new math.error.UnsupportedTypeError('asech', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/asinh.js b/lib/function/trigonometry/asinh.js new file mode 100644 index 000000000..6da74d188 --- /dev/null +++ b/lib/function/trigonometry/asinh.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAsinh = util.bignumber.acosh_asinh_asech_acsch; + + /** + * Calculate the hyperbolic arcsine of a value, + * defined as `asinh(x) = ln(x + sqrt(x^2 + 1))`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.asinh(x) + * + * Examples: + * + * math.asinh(0.5); // returns 0.4812118250596 + * + * See also: + * + * acosh, atanh + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arcsine of x + */ + math.asinh = function asinh(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('asinh', arguments.length, 1); + } + + if (isNumber(x)) { + return Math.log(x + Math.sqrt(x*x + 1)); + } + + if (isComplex(x)) { + return new Complex( + Math.log(x.re + Math.sqrt(x.re*x.re + 1)), + Math.log(x.im + Math.sqrt(x.im*x.im + 1)) + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function asinh is no angle'); + } + return asinh(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, asinh); + } + + if (isBoolean(x) || x === null) { + return (x) ? Math.log(1 + Math.SQRT2) : 0; + } + + if (x instanceof BigNumber) { + return bigAsinh(x, 1, false); + } + + throw new math.error.UnsupportedTypeError('asinh', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/atanh.js b/lib/function/trigonometry/atanh.js new file mode 100644 index 000000000..59bc0ac07 --- /dev/null +++ b/lib/function/trigonometry/atanh.js @@ -0,0 +1,77 @@ +'use strict'; + +module.exports = function (math) { + var util = require('../../util/index'), + + BigNumber = math.type.BigNumber, + Complex = require('../../type/Complex'), + Unit = require('../../type/Unit'), + collection = require('../../type/collection'), + + isNumber = util.number.isNumber, + isBoolean = util['boolean'].isBoolean, + isComplex = Complex.isComplex, + isUnit = Unit.isUnit, + isCollection = collection.isCollection, + + bigAtanh = util.bignumber.atanh_acoth; + + /** + * Calculate the hyperbolic arctangent of a value, + * defined as `atanh(x) = ln((1 + x)/(1 - x)) / 2`. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.atanh(x) + * + * Examples: + * + * math.atanh(0.5); // returns 0.4812118250596 + * + * See also: + * + * acosh, asinh + * + * @param {Number | Boolean | Complex | Unit | Array | Matrix | null} x Function input + * @return {Number | Complex | Array | Matrix} Hyperbolic arctangent of x + */ + math.atanh = function atanh(x) { + if (arguments.length != 1) { + throw new math.error.ArgumentsError('atanh', arguments.length, 1); + } + + if (isNumber(x)) { + return Math.log((1 + x)/(1 - x)) / 2; + } + + if (isComplex(x)) { + return new Complex( + Math.log((1 + x.re)/(1 - x.re)) / 2, + (Math.log(1 + x.im) - Math.log(1 - x.im)) / 2 + ); + } + + if (isUnit(x)) { + if (!x.hasBase(Unit.BASE_UNITS.ANGLE)) { + throw new TypeError('Unit in function atanh is no angle'); + } + return atanh(x.value); + } + + if (isCollection(x)) { + return collection.deepMap(x, atanh); + } + + if (isBoolean(x) || x === null) { + return (x) ? Infinity : 0; + } + + if (x instanceof BigNumber) { + return bigAtanh(x, false); + } + + throw new math.error.UnsupportedTypeError('atanh', math['typeof'](x)); + }; +}; diff --git a/lib/function/trigonometry/cos.js b/lib/function/trigonometry/cos.js index 577c6c3d0..172e5abbc 100644 --- a/lib/function/trigonometry/cos.js +++ b/lib/function/trigonometry/cos.js @@ -14,7 +14,7 @@ module.exports = function (math, config) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigCos = util.bignumber.cos_sin; + bigCos = util.bignumber.cos_sin_sec_csc; /** * Calculate the cosine of a value. @@ -75,7 +75,7 @@ module.exports = function (math, config) { } if (x instanceof BigNumber) { - return bigCos(x, config.precision, 0); + return bigCos(x, config.precision, 0, false); } throw new math.error.UnsupportedTypeError('cos', math['typeof'](x)); diff --git a/lib/function/trigonometry/cosh.js b/lib/function/trigonometry/cosh.js index b7fae2bbc..176067408 100644 --- a/lib/function/trigonometry/cosh.js +++ b/lib/function/trigonometry/cosh.js @@ -14,7 +14,7 @@ module.exports = function (math) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigCosh = util.bignumber.cosh_sinh; + bigCosh = util.bignumber.cosh_sinh_csch_sech; /** * Calculate the hyperbolic cosine of a value, @@ -68,7 +68,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - return bigCosh(x, 0); + return bigCosh(x, 0, false); } throw new math.error.UnsupportedTypeError('cosh', math['typeof'](x)); diff --git a/lib/function/trigonometry/cot.js b/lib/function/trigonometry/cot.js index 5ee767919..36f984f0f 100644 --- a/lib/function/trigonometry/cot.js +++ b/lib/function/trigonometry/cot.js @@ -1,6 +1,6 @@ 'use strict'; -module.exports = function (math) { +module.exports = function (math, config) { var util = require('../../util/index'), BigNumber = math.type.BigNumber, @@ -12,7 +12,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigCot = util.bignumber.tan_cot; /** * Calculate the cotangent of a value. `cot(x)` is defined as `1 / tan(x)`. @@ -70,9 +72,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return cot(x.toNumber()); + return bigCot(x, config.precision, true); } throw new math.error.UnsupportedTypeError('cot', math['typeof'](x)); diff --git a/lib/function/trigonometry/coth.js b/lib/function/trigonometry/coth.js index a43f2ffd4..c41e98b30 100644 --- a/lib/function/trigonometry/coth.js +++ b/lib/function/trigonometry/coth.js @@ -12,7 +12,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigCoth = util.bignumber.tanh_coth; /** * Calculate the hyperbolic cotangent of a value, @@ -74,9 +76,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return coth(x.toNumber()); + return bigCoth(x, true); } throw new math.error.UnsupportedTypeError('coth', math['typeof'](x)); diff --git a/lib/function/trigonometry/csc.js b/lib/function/trigonometry/csc.js index cacbb0a58..9d8d5c3b8 100644 --- a/lib/function/trigonometry/csc.js +++ b/lib/function/trigonometry/csc.js @@ -1,6 +1,6 @@ 'use strict'; -module.exports = function (math) { +module.exports = function (math, config) { var util = require('../../util/index'), BigNumber = math.type.BigNumber, @@ -12,7 +12,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigCsc = util.bignumber.cos_sin_sec_csc; /** * Calculate the cosecant of a value, defined as `csc(x) = 1/sin(x)`. @@ -71,9 +73,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return csc(x.toNumber()); + return bigCsc(x, config.precision, 1, true); } throw new math.error.UnsupportedTypeError('csc', math['typeof'](x)); diff --git a/lib/function/trigonometry/csch.js b/lib/function/trigonometry/csch.js index 4a2ac0df5..a6e32e412 100644 --- a/lib/function/trigonometry/csch.js +++ b/lib/function/trigonometry/csch.js @@ -13,7 +13,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigCsch = util.bignumber.cosh_sinh_csch_sech; /** * Calculate the hyperbolic cosecant of a value, @@ -45,7 +47,7 @@ module.exports = function (math) { if (isNumber(x)) { // x == 0 - if (x == 0) return Number.NaN; + if (x == 0) return Number.POSITIVE_INFINITY; // consider values close to zero (+/-) return Math.abs(2 / (Math.exp(x) - Math.exp(-x))) * number.sign(x); } @@ -75,9 +77,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return csch(x.toNumber()); + return bigCsch(x, 1, true); } throw new math.error.UnsupportedTypeError('csch', math['typeof'](x)); diff --git a/lib/function/trigonometry/sec.js b/lib/function/trigonometry/sec.js index 77087b87d..a7d3513c5 100644 --- a/lib/function/trigonometry/sec.js +++ b/lib/function/trigonometry/sec.js @@ -1,6 +1,6 @@ 'use strict'; -module.exports = function (math) { +module.exports = function (math, config) { var util = require('../../util/index'), BigNumber = math.type.BigNumber, @@ -12,7 +12,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigSec = util.bignumber.cos_sin_sec_csc; /** * Calculate the secant of a value, defined as `sec(x) = 1/cos(x)`. @@ -71,9 +73,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return sec(x.toNumber()); + return bigSec(x, config.precision, 0, true); } throw new math.error.UnsupportedTypeError('sec', math['typeof'](x)); diff --git a/lib/function/trigonometry/sech.js b/lib/function/trigonometry/sech.js index 0918233cc..d29911e58 100644 --- a/lib/function/trigonometry/sech.js +++ b/lib/function/trigonometry/sech.js @@ -12,7 +12,9 @@ module.exports = function (math) { isBoolean = util['boolean'].isBoolean, isComplex = Complex.isComplex, isUnit = Unit.isUnit, - isCollection = collection.isCollection; + isCollection = collection.isCollection, + + bigSech = util.bignumber.cosh_sinh_csch_sech; /** * Calculate the hyperbolic secant of a value, @@ -71,9 +73,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - // TODO: implement BigNumber support - // downgrade to Number - return sech(x.toNumber()); + return bigSech(x, 0, true); } throw new math.error.UnsupportedTypeError('sech', math['typeof'](x)); diff --git a/lib/function/trigonometry/sin.js b/lib/function/trigonometry/sin.js index 5c872a39c..2c100c4d5 100644 --- a/lib/function/trigonometry/sin.js +++ b/lib/function/trigonometry/sin.js @@ -14,7 +14,7 @@ module.exports = function (math, config) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigSin = util.bignumber.cos_sin; + bigSin = util.bignumber.cos_sin_sec_csc; /** * Calculate the sine of a value. @@ -74,7 +74,7 @@ module.exports = function (math, config) { } if (x instanceof BigNumber) { - return bigSin(x, config.precision, 1); + return bigSin(x, config.precision, 1, false); } throw new math.error.UnsupportedTypeError('sin', math['typeof'](x)); diff --git a/lib/function/trigonometry/sinh.js b/lib/function/trigonometry/sinh.js index 56d98df71..cdb336a97 100644 --- a/lib/function/trigonometry/sinh.js +++ b/lib/function/trigonometry/sinh.js @@ -14,7 +14,7 @@ module.exports = function (math) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigSinh = util.bignumber.cosh_sinh; + bigSinh = util.bignumber.cosh_sinh_csch_sech; /** * Calculate the hyperbolic sine of a value, @@ -74,7 +74,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - return bigSinh(x, 1); + return bigSinh(x, 1, false); } throw new math.error.UnsupportedTypeError('sinh', math['typeof'](x)); diff --git a/lib/function/trigonometry/tan.js b/lib/function/trigonometry/tan.js index 5eab0cebe..099707b42 100644 --- a/lib/function/trigonometry/tan.js +++ b/lib/function/trigonometry/tan.js @@ -14,7 +14,7 @@ module.exports = function (math, config) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigTan = util.bignumber.tan; + bigTan = util.bignumber.tan_cot; /** * Calculate the tangent of a value. `tan(x)` is equal to `sin(x) / cos(x)`. @@ -75,7 +75,7 @@ module.exports = function (math, config) { } if (x instanceof BigNumber) { - return bigTan(x, config.precision); + return bigTan(x, config.precision, false); } throw new math.error.UnsupportedTypeError('tan', math['typeof'](x)); diff --git a/lib/function/trigonometry/tanh.js b/lib/function/trigonometry/tanh.js index 56d782bd1..b70d40823 100644 --- a/lib/function/trigonometry/tanh.js +++ b/lib/function/trigonometry/tanh.js @@ -14,7 +14,7 @@ module.exports = function (math) { isUnit = Unit.isUnit, isCollection = collection.isCollection, - bigTanh = util.bignumber.tanh; + bigTanh = util.bignumber.tanh_coth; /** * Calculate the hyperbolic tangent of a value, @@ -77,7 +77,7 @@ module.exports = function (math) { } if (x instanceof BigNumber) { - return bigTanh(x); + return bigTanh(x, false); } throw new math.error.UnsupportedTypeError('tanh', math['typeof'](x)); diff --git a/lib/util/bignumber.js b/lib/util/bignumber.js index 02f47e305..14b03a771 100644 --- a/lib/util/bignumber.js +++ b/lib/util/bignumber.js @@ -484,12 +484,12 @@ function decCoefficientToBinaryString(x) { *************************************/ /** - * Calculate the arc cosine of x + * Calculate the arccosine of x * * acos(x) = 2*atan(sqrt(1-x^2)/(1+x)) * * @param {BigNumber} x - * @returns {BigNumber} arc cosine of x + * @returns {BigNumber} arccosine of x */ exports.arccos = function (x) { var Big = x.constructor; @@ -510,10 +510,10 @@ exports.arccos = function (x) { }; /** - * Calculate the arc sine of x + * Calculate the arcsine of x * * @param {BigNumber} x - * @returns {BigNumber} arc sine of x + * @returns {BigNumber} arcsine of x */ exports.arcsin = function (x) { var Big = x.constructor; @@ -568,10 +568,10 @@ exports.arcsin = function (x) { }; /** - * Calculate the arc tangent of x + * Calculate the arctangent of x * * @param {BigNumber} x - * @returns {BigNumber} arc tangent of x + * @returns {BigNumber} arctangent of x */ exports.arctan = function (x) { var Big = x.constructor; @@ -589,10 +589,10 @@ exports.arctan = function (x) { return halfPi; } + Big.config({precision: precision + 4}); + var absX = x.abs(); if (absX.lte(0.875)) { - Big.config({precision: precision + 4}); - var ret = arctan_taylor(x); ret.constructor = Big; @@ -600,8 +600,6 @@ exports.arctan = function (x) { 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(absX))); @@ -613,15 +611,103 @@ exports.arctan = function (x) { } // arctan(x) = arcsin(x / [sqrt(1 + x^2)]) - Big.config({precision: precision + 4}); x = x.div(x.times(x).plus(1).sqrt()); - Big.config({precision: precision}); + Big.config({precision: precision}); return exports.arcsin(x); }; /** - * Calculate cosine/sine of x using the multiple angle identity: + * Calculate the hyperbolic arccosine, arcsine, arcsecant, or arccosecant of x + * + * acosh(x) = ln(x + sqrt(x^2 - 1)) + * + * asinh(x) = ln(x + sqrt(x^2 + 1)) + * + * asech(x) = 1 / ln(x + sqrt(x^2 - 1)) + * + * acsch(x) = 1 / ln(x + sqrt(x^2 + 1)) + * + * @param {BigNumber} x + * @param {Number} mode cosine function if 0, sine function if 1 + * @param {Boolean} reciprocal is sec or csc + * @returns {BigNumber} hyperbolic arccosine, arcsine, arcsecant, or arccosecant of x + */ +exports.acosh_asinh_asech_acsch = function (x, mode, reciprocal) { + var Big = x.constructor; + if (x.isNaN()) { + return new Big(NaN); + } + if (reciprocal && x.isZero()) { + return new Big(Infinity); + } + if (!mode) { + if (reciprocal) { + if (x.isNegative() || x.gt(Big.ONE)) { + throw new Error('asech() only has non-complex values for 0 <= x <= 1.'); + } + } else { + if (x.lt(Big.ONE)) { + throw new Error('acosh() only has non-complex values for x >= 1.'); + } + } + } + + var precision = Big.precision; + Big.config({precision: precision + 4}); + + var plusOrMinus = (mode) ? x.plus : x.minus; + var ret = x.plus(x.times(x).plusOrMinus(Big.ONE).sqrt()).ln(); + if (reciprocal) { + ret = Big.ONE.div(ret); + } + + Big.config({precision: precision}); + return new Big(ret.toPrecision(precision)); +}; + +/** + * Calculate the hyperbolic arctangent or arccotangent of x + * + * atanh(x) = ln((1 + x)/(1 - x)) / 2 + * + * @param {BigNumber} x + * @param {Boolean} reciprocal is sec or csc + * @returns {BigNumber} hyperbolic arctangent or arccotangent of x + */ +exports.atanh_acoth = function (x, reciprocal) { + var Big = x.constructor; + if (x.isNaN()) { + return new Big(NaN); + } + if (x.isZero()) { + return new Big(0); + } + + var absX = x.abs(); + if (absX.eq(Big.ONE)) { + return new Big(x.isNegative() ? -Infinity : Infinity); + } + if (abs.gt(Big.ONE)) { + if (!reciprocal) { + throw new Error('atanh() only has non-complex values for |x| <= 1.'); + } + } else if (reciprocal) { + throw new Error('acoth() has complex values for |x| < 1, except x = 0.'); + } + + var precision = Big.precision; + Big.config({precision: precision + 4}); + + var ret = Big.ONE.plus(x).div(Big.ONE.minus(x)).ln(); + ret = (reciprocal) ? new Big(2).div(ret) : ret.div(2); + + Big.config({precision: precision}); + return new Big(ret.toPrecision(precision)); +}; + +/** + * Calculate the cosine/sine of x using the multiple angle identity: * * cos(4x) = 8[cos(x)^4 - cos(x)^2] + 1 * @@ -630,10 +716,11 @@ exports.arctan = function (x) { * * @param {BigNumber} x * @param {Number} precision precision as defined in the config file - * @param {Number} mode sine function if 1, cosine function if 0 - * @returns {BigNumber} sine or cosine of x + * @param {Number} mode cosine function if 0, sine function if 1 + * @param {Boolean} reciprocal is sec or csc + * @returns {BigNumber} cosine, sine, secant, or cosecant of x */ -exports.cos_sin = function (x, precision, mode) { +exports.cos_sin_sec_csc = function (x, precision, mode, reciprocal) { var Big; if (x.isNaN() || !x.isFinite()) { Big = BigNumber.constructor({precision: precision}); @@ -651,13 +738,18 @@ exports.cos_sin = function (x, precision, mode) { } // Apply ~log(precision) guard bits - var precPlusGuardDigits = precision + (Math.log(precision) | 0) + 3; + var precPlusGuardDigits = precision + (Math.log(precision) | 0) + 3; Big.config({precision: precPlusGuardDigits}); y = reduceToPeriod(y, precPlusGuardDigits, mode); // Make this destructive if (y[1]) { + y = y[0]; + if (reciprocal && y.isZero()) { + y = new Big(Infinity); + } + Big.config({precision: precision}); - return y[0]; + return y; } var ret; @@ -702,6 +794,12 @@ exports.cos_sin = function (x, precision, mode) { } } + if (reciprocal) { + ret = (ret.e <= -precision) + ? new Big(Infinity) + : Big.ONE.div(ret); + } + ret.constructor.config({precision: precision}); return ret.toDP(precision - 1); }; @@ -711,11 +809,14 @@ exports.cos_sin = function (x, precision, mode) { * * tan(x) = sin(x) / cos(x) * + * cot(x) = cos(x) / sin(x) + * * @param {BigNumber} x * @param {Number} precision precision as defined in the config file - * @returns {BigNumber} tangent of x + * @param {Boolean} reciprocal is cot + * @returns {BigNumber} tangent or cotangent of x */ -exports.tan = function (x, precision) { +exports.tan_cot = function (x, precision, reciprocal) { var Big = BigNumber.constructor({precision: precision}); if (x.isNaN()) { return new Big(NaN); @@ -730,7 +831,7 @@ exports.tan = function (x, precision) { return new Big(Infinity); } - var sin = exports.cos_sin(y, precision + 2, 1); + var sin = exports.cos_sin_sec_csc(y, precision + 2, 1, false); var cos = sinToCos(sin); sin.constructor.config({precision: precision}); @@ -747,13 +848,13 @@ exports.tan = function (x, precision) { } sin.constructor.config({precision: precision + 2}); - var tan = sin.div(cos); + var tan = (reciprocal) ? cos.div(sin) : sin.div(cos); return new Big(tan.toPrecision(precision)); }; /** - * Calculate the hyperbolic cosine/sine of x + * Calculate the hyperbolic sine, cosine, secant, or cosecant of x * * cosh(x) = (exp(x) + exp(-x)) / 2 * = (e^x + 1/e^x) / 2 @@ -761,16 +862,26 @@ exports.tan = function (x, precision) { * sinh(x) = (exp(x) - exp(-x)) / 2 * = (e^x - 1/e^x) / 2 * + * sech(x) = 2 / (exp(x) + exp(-x)) + * = 2 / (e^x + 1/e^x) + * + * csch(x) = 2 / (exp(x) - exp(-x)) + * = 2 / (e^x - 1/e^x) + * * @param {BigNumber} x - * @param {Number} mode cosh function if 0, sinh function if 1 - * @returns {BigNumber} cosh or sinh of x + * @param {Number} mode cosh function if 0, sinh function if 1 + * @param {Boolean} reciprocal is sech or csch + * @returns {BigNumber} hyperbolic cosine, sine, secant. or cosecant of x */ -exports.cosh_sinh = function (x, mode) { +exports.cosh_sinh_csch_sech = function (x, mode, reciprocal) { var Big = x.constructor; if (x.isNaN()) { return new Big(NaN); } if (!x.isFinite()) { + if (reciprocal) { + return new Big(0); + } return new Big((mode) ? x : Infinity); } @@ -779,7 +890,7 @@ exports.cosh_sinh = function (x, mode) { var y = x.exp(); y = (mode) ? y.minus(Big.ONE.div(y)) : y.plus(Big.ONE.div(y)); - y = y.div(2); + y = (reciprocal) ? new Big(2).div(y) : y.div(2); Big.config({precision: precision}); return new Big(y.toPrecision(precision)); @@ -792,10 +903,15 @@ exports.cosh_sinh = function (x, mode) { * = (exp(2x) - 1) / (exp(2x) + 1) * = (e^x - 1/e^x) / (e^x + 1/e^x) * + * coth(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) + * = (exp(2x) + 1) / (exp(2x) - 1) + * = (e^x + 1/e^x) / (e^x - 1/e^x) + * * @param {BigNumber} x - * @returns {BigNumber} tanh of x + * @param {Boolean} reciprocal is coth + * @returns {BigNumber} hyperbolic tangent or cotangent of x */ -exports.tanh = function (x) { +exports.tanh_coth = function (x, reciprocal) { var Big = x.constructor; if (x.isNaN()) { return new Big(NaN); @@ -810,7 +926,7 @@ exports.tanh = function (x) { var posExp = x.exp(); var negExp = Big.ONE.div(posExp); var ret = posExp.minus(negExp); - ret = ret.div(posExp.plus(negExp)); + ret = (reciprocal) ? posExp.plus(negExp).div(ret) : ret.div(posExp.plus(negExp)); Big.config({precision: precision}); return ret.toDP(precision - 1); @@ -841,7 +957,7 @@ function arcsin_newton(x, oldPrecision) { var i = 0; do { - var tmp0 = exports.cos_sin(curr, localPrecision, 1); + var tmp0 = exports.cos_sin_sec_csc(curr, localPrecision, 1, false); var tmp1 = sinToCos(tmp0); if (!tmp0.isZero()) { tmp0.s = curr.s; diff --git a/test/function/trigonometry/acos.test.js b/test/function/trigonometry/acos.test.js index c252ee3ea..807501bb5 100644 --- a/test/function/trigonometry/acos.test.js +++ b/test/function/trigonometry/acos.test.js @@ -63,6 +63,15 @@ describe('acos', function() { assert.deepEqual(acos(bigmath.cos(Big(2))).toString(), '2'); }); + it('should throw an error if the bignumber result is complex', function() { + assert.throws(function () { + acos(Big(1.1)); + }, /acos() only has non-complex values for |x| <= 1./); + assert.throws(function () { + acos(Big(-1.1)); + }, /acos() only has non-complex values for |x| <= 1./); + }); + 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)); diff --git a/test/function/trigonometry/asin.test.js b/test/function/trigonometry/asin.test.js index eb3e72d34..7542e2959 100644 --- a/test/function/trigonometry/asin.test.js +++ b/test/function/trigonometry/asin.test.js @@ -84,6 +84,15 @@ describe('asin', function() { assert.deepEqual(asin(bigmath.sin(Big(2))).toString(), '1.1415926535897932385'); }); + it('should throw an error if the bignumber result is complex', function() { + assert.throws(function () { + asin(Big(1.1)); + }, /asin() only has non-complex values for |x| <= 1./); + assert.throws(function () { + asin(Big(-1.1)); + }, /asin() only has non-complex values for |x| <= 1./); + }); + it('should return the arcsin of a complex number', function() { var re = 0.570652784321099; var im = 1.983387029916536; diff --git a/test/function/trigonometry/cot.test.js b/test/function/trigonometry/cot.test.js index d236693bb..d4deb851b 100644 --- a/test/function/trigonometry/cot.test.js +++ b/test/function/trigonometry/cot.test.js @@ -6,7 +6,9 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - cot = math.cot; + cot = math.cot, + bigmath = math.create({number: 'bignumber', precision: 20}), + biggermath = math.create({number: 'bignumber', precision: 22}); describe('cot', function() { it('should return the cotan of a boolean', function () { @@ -20,8 +22,8 @@ describe('cot', function() { it('should return the cotan of a number', function() { approx.equal(cot(0), Infinity); - approx.equal(1 / cot(pi*1/4), 1); approx.equal(1 / cot(pi*1/8), 0.414213562373095); + approx.equal(1 / cot(pi*1/4), 1); approx.equal(cot(pi*2/4), 0); approx.equal(1 / cot(pi*3/4), -1); approx.equal(1 / cot(pi*4/4), 0); @@ -31,8 +33,34 @@ describe('cot', function() { approx.equal(1 / cot(pi*8/4), 0); }); - it('should return the cotan of a bignumber (downgrades to number)', function() { - approx.equal(cot(math.bignumber(1)), 0.642092615934331); + it('should return the cotan of a bignumber', function() { + var Big = bigmath.bignumber; + var bigPi = bigmath.pi; + var sqrt2 = bigmath.SQRT2.toString(); + + var arg1 = Big(0); + var result1 = bigmath.cot(arg1); + assert.ok(!result1.isFinite()); + assert.equal(result1.constructor.precision, 20); + assert.deepEqual(arg1, Big(0)); + + var result2 = bigmath.cot(bigPi.div(8)); + assert.deepEqual(result2.toString(), '2.4142135623730950488'); + assert.equal(result2.constructor.precision, 20); + assert.equal(bigPi.constructor.precision, 20); + + assert.ok(bigmath.cot(bigPi.div(2)).isZero()); + assert.ok(!bigmath.cot(bigPi).isFinite()); + assert.ok(bigmath.cot(bigPi.times(3).div(2)).isZero()); + assert.ok(!bigmath.cot(bigPi.times(2)).isFinite()); + assert.ok(!bigmath.cot(bigmath.tau).isFinite()); + + /* Pass in more digits of pi. */ + bigPi = biggermath.pi; + assert.deepEqual(bigmath.cot(bigPi.div(4)).toString(), '1'); + assert.deepEqual(bigmath.cot(bigPi.times(3).div(4)).toString(), '-1'); + assert.deepEqual(bigmath.cot(bigPi.times(5).div(4)).toString(), '1'); + assert.deepEqual(bigmath.cot(bigPi.times(7).div(4)).toString(), '-1'); }); it('should return the cotan of a complex number', function() { @@ -75,4 +103,4 @@ describe('cot', function() { assert.throws(function () {cot(1, 2)}, error.ArgumentsError); }); -}); \ No newline at end of file +}); diff --git a/test/function/trigonometry/coth.test.js b/test/function/trigonometry/coth.test.js index a43f02d89..273899d71 100644 --- a/test/function/trigonometry/coth.test.js +++ b/test/function/trigonometry/coth.test.js @@ -6,7 +6,8 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - coth = math.coth; + coth = math.coth, + bigmath = math.create({number: 'bignumber', precision: 20}); describe('coth', function() { it('should return the coth of a boolean', function () { @@ -26,8 +27,15 @@ describe('coth', function() { approx.equal(coth(3), 1.0049698233137); }); - it('should return the coth of a bignumber (downgrades to number)', function() { - approx.equal(coth(math.bignumber(1)), 1.3130352854993); + it('should return the coth of a bignumber', function() { + var Big = bigmath.bignumber; + assert.deepEqual(coth(Big(0)), Big(Number.POSITIVE_INFINITY)); + assert.deepEqual(coth(Big(1)), Big('1.3130352854993313036')); + assert.deepEqual(coth(Big(2)), Big('1.0373147207275480959')); + assert.deepEqual(coth(Big(3)), Big('1.0049698233136891711')); + + /* Pass in extra digits to pi. */ + //assert.deepEqual(coth(bigmath.pi), Big('0.0862667383340544147')); }); it('should return the coth of a complex number', function() { diff --git a/test/function/trigonometry/csc.test.js b/test/function/trigonometry/csc.test.js index fac77d362..11b625b47 100644 --- a/test/function/trigonometry/csc.test.js +++ b/test/function/trigonometry/csc.test.js @@ -6,7 +6,9 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - csc = math.csc; + csc = math.csc, + bigmath = math.create({number: 'bignumber', precision: 20}), + biggermath = math.create({number: 'bignumber', precision: 21}); describe('csc', function() { it('should return the cosecant of a boolean', function () { @@ -32,8 +34,25 @@ describe('csc', function() { approx.equal(1 / csc(pi/4), math.sqrt(2)/2); }); - it('should return the cosecant of a bignumber (downgrades to number)', function() { - approx.equal(csc(math.bignumber(1)), 1.18839510577812); + it('should return the cosecant of a bignumber', function() { + var Big = bigmath.bignumber; + var bigPi = bigmath.pi; + var sqrt2 = bigmath.SQRT2.toString(); + + assert.ok(!bigmath.csc(Big(0)).isFinite()); + assert.deepEqual(bigmath.csc(bigPi.div(8)).toString(), '2.6131259297527530557'); + assert.deepEqual(bigmath.csc(bigPi.div(4)).toString(), sqrt2); + assert.deepEqual(bigmath.csc(bigPi.div(2)).toString(), '1'); + assert.ok(!bigmath.csc(bigPi).isFinite()); + assert.deepEqual(bigmath.csc(bigPi.times(3).div(2)).toString(), '-1'); + assert.ok(!bigmath.csc(bigPi.times(2)).isFinite()); + assert.ok(!bigmath.csc(bigmath.tau).isFinite()); + + /* Pass in more digits of pi. */ + bigPi = biggermath.pi; + assert.deepEqual(bigmath.csc(bigPi.times(3).div(4)).toString(), sqrt2); + assert.deepEqual(bigmath.csc(bigPi.times(5).div(4)).toString(), '-'+sqrt2); + assert.deepEqual(bigmath.csc(bigPi.times(7).div(4)).toString(), '-'+sqrt2); }); it('should return the cosecant of a complex number', function() { @@ -76,4 +95,4 @@ describe('csc', function() { assert.throws(function () {csc(1, 2)}, error.ArgumentsError); }); -}); \ No newline at end of file +}); diff --git a/test/function/trigonometry/csch.test.js b/test/function/trigonometry/csch.test.js index 8dbc2555f..c9fb33096 100644 --- a/test/function/trigonometry/csch.test.js +++ b/test/function/trigonometry/csch.test.js @@ -6,31 +6,39 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - csch = math.csch; + csch = math.csch, + bigmath = math.create({number: 'bignumber', precision: 20}); describe('csch', function() { it('should return the csch of a boolean', function () { approx.equal(csch(true), 0.85091812823932); - approx.equal(csch(false), Number.NaN); + approx.equal(csch(false), Number.POSITIVE_INFINITY); }); it('should return the csch of null', function () { - approx.equal(csch(null), Number.NaN); + approx.equal(csch(null), Number.POSITIVE_INFINITY); }); it('should return the csch of a number', function() { - approx.equal(csch(0), Number.NaN); + approx.equal(csch(0), Number.POSITIVE_INFINITY); approx.equal(csch(pi), 0.086589537530047); approx.equal(csch(1), 0.85091812823932); approx.equal(csch(2), 0.27572056477178); approx.equal(csch(3), 0.099821569668823); - approx.equal(csch(3), 0.099821569668823); approx.equal(csch(1e-22), Number.POSITIVE_INFINITY); approx.equal(csch(-1e-22), Number.NEGATIVE_INFINITY); }); - it('should return the csch of a bignumber (downgrades to number)', function() { - approx.equal(csch(math.bignumber(1)), 0.85091812823932); + it('should return the csch of a bignumber', function() { + var Big = bigmath.bignumber; + + assert.deepEqual(csch(Big(0)), Big(Infinity)); + assert.deepEqual(csch(Big(1)), Big('0.85091812823932154513')); + assert.deepEqual(csch(Big(2)), Big('0.27572056477178320776')); + assert.deepEqual(csch(Big(3)), Big('0.099821569668822732851')); + + /* Pass in extra digits to pi. */ + //assert.deepEqual(csch(bigmath.pi).toString(), '0.086589537530046941828'); }); it('should return the csch of a complex number', function() { diff --git a/test/function/trigonometry/sec.test.js b/test/function/trigonometry/sec.test.js index 1c352fb3c..041f62207 100644 --- a/test/function/trigonometry/sec.test.js +++ b/test/function/trigonometry/sec.test.js @@ -6,7 +6,9 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - sec = math.sec; + sec = math.sec, + bigmath = math.create({number: 'bignumber', precision: 20}), + biggermath = math.create({number: 'bignumber', precision: 21}); describe('sec', function() { it('should return the secant of a boolean', function () { @@ -40,8 +42,26 @@ describe('sec', function() { approx.equal(sec(-2*pi), 1); }); - it('should return the secant of a bignumber (downgrades to number)', function() { - approx.equal(sec(math.bignumber(1)), 1.85081571768093); + it('should return the secant of a bignumber', function() { + var Big = bigmath.bignumber; + var bigPi = bigmath.pi; + var sqrt2 = bigmath.SQRT2.toString(); + + assert.deepEqual(bigmath.sec(Big(0)).toString(), '1'); + assert.deepEqual(bigmath.sec(bigPi.div(8)).toString(), '1.0823922002923939688'); + assert.deepEqual(bigmath.sec(bigPi.div(4)).toString(), sqrt2); + assert.deepEqual(bigmath.sec(bigPi).toString(), '-1'); + assert.deepEqual(bigmath.sec(bigPi.times(2)).toString(), '1'); + assert.deepEqual(bigmath.sec(bigmath.tau).toString(), '1'); + assert.deepEqual(bigmath.sec(bigmath.tau.times(-2)).toString(), '1'); + + /* Pass in one more digit of pi. */ + bigPi = biggermath.pi; + assert.ok(!bigmath.sec(bigPi.div(2)).isFinite()); + assert.deepEqual(bigmath.sec(bigPi.times(3).div(4)).toString(), '-'+sqrt2); + assert.deepEqual(bigmath.sec(bigPi.times(5).div(4)).toString(), '-'+sqrt2); + assert.ok(!bigmath.sec(bigPi.times(3).div(2)).isFinite()); + assert.deepEqual(bigmath.sec(bigPi.times(7).div(4)).toString(), sqrt2); }); it('should return the secant of a complex number', function() { @@ -84,4 +104,4 @@ describe('sec', function() { assert.throws(function () {sec(1, 2)}, error.ArgumentsError); }); -}); \ No newline at end of file +}); diff --git a/test/function/trigonometry/sech.test.js b/test/function/trigonometry/sech.test.js index 5def6f533..74d426039 100644 --- a/test/function/trigonometry/sech.test.js +++ b/test/function/trigonometry/sech.test.js @@ -6,7 +6,8 @@ var assert = require('assert'), complex = math.complex, matrix = math.matrix, unit = math.unit, - sech = math.sech; + sech = math.sech, + bigmath = math.create({number: 'bignumber', precision: 20}); describe('sech', function() { it('should return the sech of a boolean', function () { @@ -26,8 +27,16 @@ describe('sech', function() { approx.equal(sech(3), 0.099327927419433); }); - it('should return the sech of a bignumber (downgrades to number)', function() { - approx.equal(sech(math.bignumber(1)), 0.64805427366389); + it('should return the sech of a bignumber', function() { + var Big = bigmath.bignumber; + + assert.deepEqual(sech(Big(0)), Big(1)); + assert.deepEqual(sech(Big(1)), Big('0.64805427366388539957')); + assert.deepEqual(sech(Big(2)), Big('0.26580222883407969212')); + assert.deepEqual(sech(Big(3)), Big('0.099327927419433207829')); + + /* Pass in extra digits to pi. */ + //assert.deepEqual(sech(bigmath.pi), Big('0.0862667383340544147')); }); it('should return the sech of a complex number', function() {