diff --git a/decimal.js b/decimal.js index 511028e..e58df57 100644 --- a/decimal.js +++ b/decimal.js @@ -2629,9 +2629,9 @@ */ function cosine(Ctor, x) { var k, len, y; - + if (x.isZero()) return x; - + // Argument reduction: cos(4x) = 8*(cos^4(x) - cos^2(x)) + 1 // i.e. cos(x) = 8*(cos^4(x/4) - cos^2(x/4)) + 1 @@ -3665,10 +3665,10 @@ function sine(Ctor, x) { var k, len = x.d.length; - + if (len < 3) { return x.isZero() ? x : taylorSeries(Ctor, 2, x, x); - } + } // Argument reduction: sin(5x) = 16*sin^5(x) - 20*sin^3(x) + 5*sin(x) // i.e. sin(x) = 16*sin^5(x/5) - 20*sin^3(x/5) + 5*sin(x/5) @@ -3959,6 +3959,7 @@ * sinh * sqrt * sub + * sum * tan * tanh * trunc @@ -4407,6 +4408,7 @@ Decimal.sinh = sinh; // ES6 Decimal.sqrt = sqrt; Decimal.sub = sub; + Decimal.sum = sum; Decimal.tan = tan; Decimal.tanh = tanh; // ES6 Decimal.trunc = trunc; // ES6 @@ -4801,6 +4803,28 @@ } + /* + * Return a new Decimal whose value is the sum of the arguments, rounded to `precision` + * significant digits using rounding mode `rounding`. + * + * Only the result is rounded, not the intermediate calculations. + * + * arguments {number|string|Decimal} + * + */ + function sum() { + var i = 0, + args = arguments, + x = new this(args[i]); + + external = false; + for (; x.s && ++i < args.length;) x = x.plus(args[i]); + external = true; + + return finalise(x, this.precision, this.rounding); + } + + /* * Return a new Decimal whose value is the tangent of `x`, rounded to `precision` significant * digits using rounding mode `rounding`. diff --git a/decimal.mjs b/decimal.mjs index 81b7086..a319764 100644 --- a/decimal.mjs +++ b/decimal.mjs @@ -2624,13 +2624,15 @@ function convertBase(str, baseIn, baseOut) { * */ function cosine(Ctor, x) { - var k, y, - len = x.d.length; + var k, len, y; + + if (x.isZero()) return x; // Argument reduction: cos(4x) = 8*(cos^4(x) - cos^2(x)) + 1 // i.e. cos(x) = 8*(cos^4(x/4) - cos^2(x/4)) + 1 // Estimate the optimum number of times to use the argument reduction. + len = x.d.length; if (len < 32) { k = Math.ceil(len / 3); y = (1 / tinyPow(4, k)).toString(); @@ -3660,7 +3662,9 @@ function sine(Ctor, x) { var k, len = x.d.length; - if (len < 3) return taylorSeries(Ctor, 2, x, x); + if (len < 3) { + return x.isZero() ? x : taylorSeries(Ctor, 2, x, x); + } // Argument reduction: sin(5x) = 16*sin^5(x) - 20*sin^3(x) + 5*sin(x) // i.e. sin(x) = 16*sin^5(x/5) - 20*sin^3(x/5) + 5*sin(x/5) @@ -3951,6 +3955,7 @@ function truncate(arr, len) { * sinh * sqrt * sub + * sum * tan * tanh * trunc @@ -4399,6 +4404,7 @@ function clone(obj) { Decimal.sinh = sinh; // ES6 Decimal.sqrt = sqrt; Decimal.sub = sub; + Decimal.sum = sum; Decimal.tan = tan; Decimal.tanh = tanh; // ES6 Decimal.trunc = trunc; // ES6 @@ -4793,6 +4799,28 @@ function sub(x, y) { } +/* + * Return a new Decimal whose value is the sum of the arguments, rounded to `precision` + * significant digits using rounding mode `rounding`. + * + * Only the result is rounded, not the intermediate calculations. + * + * arguments {number|string|Decimal} + * + */ +function sum() { + var i = 0, + args = arguments, + x = new this(args[i]); + + external = false; + for (; x.s && ++i < args.length;) x = x.plus(args[i]); + external = true; + + return finalise(x, this.precision, this.rounding); +} + + /* * Return a new Decimal whose value is the tangent of `x`, rounded to `precision` significant * digits using rounding mode `rounding`. diff --git a/doc/API.html b/doc/API.html index 9eb8e14..7af7e90 100644 --- a/doc/API.html +++ b/doc/API.html @@ -102,6 +102,7 @@ li span{float:right;margin-right:10px;color:#c0c0c0}
  • sinh
  • sqrt
  • sub
  • +
  • sum
  • tan
  • tanh
  • trunc
  • @@ -601,7 +602,7 @@ a.equals(b) // true
    - max.max([x [, y, ...]]) ⇒ Decimal + max.max(x [, y, ...]) ⇒ Decimal

    x: number|string|Decimal
    @@ -613,7 +614,7 @@ a.equals(b) // true

    - min.min([x [, y, ...]]) ⇒ Decimal + min.min(x [, y, ...]) ⇒ Decimal

    x: number|string|Decimal
    @@ -833,7 +834,7 @@ a.equals(b) // true -

    sub.sub(x, y) ⇒ Decimal
    +
    sub.sub(x, y) ⇒ Decimal

    x: number|string|Decimal
    y: number|string|Decimal @@ -845,7 +846,26 @@ a.equals(b) // true -

    tan.tan(x) ⇒ Decimal
    +
    sum.sum(x [, y, ...]) ⇒ Decimal
    +

    + x: number|string|Decimal
    + y: number|string|Decimal +

    +

    + Returns a new Decimal whose value is the sum of the arguments, + rounded to precision significant digits using + rounding mode rounding.
    + Only the result is rounded, not the intermediate summations. +

    +
    +x = 5
    +y = '16'
    +z = new Decimal(-11)
    +Decimal.sum(x, y, z)           // '10'
    + + + +
    tan.tan(x) ⇒ Decimal

    x: number|string|Decimal

    See tangent.

    a = Decimal.tan(x)
    diff --git a/test/modules/sum.js b/test/modules/sum.js
    new file mode 100644
    index 0000000..6dda6f0
    --- /dev/null
    +++ b/test/modules/sum.js
    @@ -0,0 +1,64 @@
    +if (typeof T === 'undefined') require('../setup');
    +
    +T('sum', function () {
    +  var expected;
    +
    +  function t() {
    +    T.assertEqualDecimal(expected, Decimal.sum.apply(Decimal, arguments));
    +  }
    +
    +  expected = new Decimal(0);
    +
    +  t('0');
    +  t('0', new Decimal(0));
    +  t(1, 0, '-1');
    +  t(0, new Decimal('-10'), 0, 0, 0, 0, 0, 10);
    +  t(11, -11);
    +  t(1, '2', new Decimal(3), new Decimal('4'), -10);
    +  t(new Decimal(-10), '9', new Decimal(0.01), 0.99);
    +  
    +  expected = new Decimal(10);
    +
    +  t('10');
    +  t('0', new Decimal('10'));
    +  t(10, 0);
    +  t(0, 0, 0, 0, 0, 0, 10);
    +  t(11, -1);
    +  t(1, '2', new Decimal(3), new Decimal('4'));
    +  t('9', new Decimal(0.01), 0.99);
    +
    +  expected = new Decimal(600);
    +
    +  t(100, 200, 300);
    +  t('100', '200', '300');
    +  t(new Decimal(100), new Decimal(200), new Decimal(300));
    +  t(100, '200', new Decimal(300));
    +  t(99.9, 200.05, 300.05);
    +
    +  expected = new Decimal(NaN);
    +
    +  t(NaN);
    +  t('1', NaN);
    +  t(100, 200, NaN);
    +  t(NaN, 0, '9', new Decimal(0), 11, Infinity);
    +  t(0, new Decimal('-Infinity'), '9', new Decimal(NaN), 11);
    +  t(4, '-Infinity', 0, '9', new Decimal(0), Infinity, 2);
    +
    +  expected = new Decimal(Infinity);
    +
    +  t(Infinity);
    +  t(1, '1e10000000000000000000000000000000000000000', '4');
    +  t(100, 200, 'Infinity');
    +  t(0, new Decimal('Infinity'), '9', new Decimal(0), 11);
    +  t(0, '9', new Decimal(0), 11, Infinity);
    +  t(4, new Decimal(Infinity), 0, '9', new Decimal(0), Infinity, 2);
    +
    +  expected = new Decimal(-Infinity);
    +
    +  t(-Infinity);
    +  t(1, '-1e10000000000000000000000000000000000000000', '4');
    +  t(100, 200, '-Infinity');
    +  t(0, new Decimal('-Infinity'), '9', new Decimal(0), 11);
    +  t(0, '9', new Decimal(0), 11, -Infinity);
    +  t(4, new Decimal(-Infinity), 0, '9', new Decimal(0), -Infinity, 2);
    +});
    \ No newline at end of file
    diff --git a/test/test.html b/test/test.html
    index fd07521..7412f16 100644
    --- a/test/test.html
    +++ b/test/test.html
    @@ -59,6 +59,7 @@
         'sin',
         'sinh',
         'sqrt',
    +    'sum',
         'tan',
         'tanh',
         'times',
    diff --git a/test/test.js b/test/test.js
    index cdf4aca..bcc42f4 100644
    --- a/test/test.js
    +++ b/test/test.js
    @@ -46,6 +46,7 @@ console.log('\n Testing decimal.js\n');
       'sin',
       'sinh',
       'sqrt',
    +  'sum',
       'tan',
       'tanh',
       'times',