From e44d76a3d452a70303448ab0efcaa4e4448eb124 Mon Sep 17 00:00:00 2001 From: emanbau Date: Mon, 11 Dec 2023 14:07:45 -0500 Subject: [PATCH] Implementation of discrete summations --- src/factoriesAny.js | 1 + src/factoriesNumber.js | 1 + src/function/arithmetic/summation.js | 45 +++++++++++++++++++ .../function/arithmetic/summation.test.js | 22 +++++++++ 4 files changed, 69 insertions(+) create mode 100644 src/function/arithmetic/summation.js create mode 100644 test/unit-tests/function/arithmetic/summation.test.js diff --git a/src/factoriesAny.js b/src/factoriesAny.js index e9ae77caa1..dc871cb0fc 100644 --- a/src/factoriesAny.js +++ b/src/factoriesAny.js @@ -53,6 +53,7 @@ export { createSign } from './function/arithmetic/sign.js' export { createSqrt } from './function/arithmetic/sqrt.js' export { createSquare } from './function/arithmetic/square.js' export { createSubtract } from './function/arithmetic/subtract.js' +export { createSummation } from './function/arithmetic/summation.js' export { createXgcd } from './function/arithmetic/xgcd.js' export { createInvmod } from './function/arithmetic/invmod.js' export { createDotMultiply } from './function/arithmetic/dotMultiply.js' diff --git a/src/factoriesNumber.js b/src/factoriesNumber.js index 3d2ee31ef8..86c35ad460 100644 --- a/src/factoriesNumber.js +++ b/src/factoriesNumber.js @@ -122,6 +122,7 @@ export const createSign = /* #__PURE__ */ createNumberFactory('sign', signNumber export const createSqrt = /* #__PURE__ */ createNumberFactory('sqrt', sqrtNumber) export const createSquare = /* #__PURE__ */ createNumberFactory('square', squareNumber) export const createSubtract = /* #__PURE__ */ createNumberFactory('subtract', subtractNumber) +export { createSummation } from './function/arithmetic/summation.js' export const createXgcd = /* #__PURE__ */ createNumberFactory('xgcd', xgcdNumber) export const createDivideScalar = /* #__PURE__ */ createNumberFactory('divideScalar', divideNumber) export const createPow = /* #__PURE__ */ createNumberFactory('pow', powNumber) diff --git a/src/function/arithmetic/summation.js b/src/function/arithmetic/summation.js new file mode 100644 index 0000000000..56db358829 --- /dev/null +++ b/src/function/arithmetic/summation.js @@ -0,0 +1,45 @@ +import { isInteger } from '../../utils/number.js' +import { factory } from '../../utils/factory.js' + +const name = 'summation' +const dependencies = ['typed', 'numeric'] + +export const createSummation = /* #__PURE__ */ factory(name, dependencies, ({ typed, numeric }) => { + /** + * Takes two integer values start, and end, and a functrion. + * Calculates the summation of the function over the start to end range. + * + * Syntax: + * + * math.summation(start, end, func)) + * + * Examples: + * + * // Summation of squares from 1 to 5: 1^2 + 2^2 + 3^2 + 4^2 + 5^2 + * math.sum(1, 5, x => x ** 2) // returns 55 + * + * This function does not support collections (Array or Matrix). + * + * @param {number} start Start + * @param {number} end Denominator + * @param {function} func f(n) + * @return {number | BigNumber | Fraction} Sum of f(n) for n from [start, end] + */ + return typed(name, { + 'number, number, function': function (start, end, func) { + if (!isInteger(start) || !isInteger(end)) { + throw new Error('For summations, start and end must be integers') + } + if (start > end) { + throw new Error('For summations, start must be greater than, or equal to end') + } + + let sum = 0 + for (let i = start; i <= end; i++) { + sum += func(i) + } + + return sum + } + }) +}) diff --git a/test/unit-tests/function/arithmetic/summation.test.js b/test/unit-tests/function/arithmetic/summation.test.js new file mode 100644 index 0000000000..a49df81c8b --- /dev/null +++ b/test/unit-tests/function/arithmetic/summation.test.js @@ -0,0 +1,22 @@ +import assert from 'assert' + +import math from '../../../../src/defaultInstance.js' + +const summation = math.summation + +describe('summation', function () { + it('should produce the sum of a function over a range from start to end', function () { + assert.deepEqual(summation(1, 5, x => x ** 2), 55) + assert.deepEqual(summation(1, 4, x => x ** 3, 100)) + }) + + it('should throw an error if start or end are not integers', function () { + assert.throws(function () { summation(1.1, 2.2, x => x ** 2) }) + assert.throws(function () { summation(1.1, 2, x => x ** 2) }) + assert.throws(function () { summation(1, 2.4, x => x ** 2) }) + }) + + it('should throw an error if end is less than start', function () { + assert.throws(function () { summation(2, 1, x => x ** 2) }) + }) +})