From eed30c6bf8604d9bf116ff57a8277f15bf482b3d Mon Sep 17 00:00:00 2001 From: ggkogkou Date: Wed, 27 Oct 2021 22:56:47 +0300 Subject: [PATCH 1/6] Created composite Simpson's integration method.Tests included --- Maths/SimpsonIntegration.js | 69 +++++++++++++++++++++++++++ Maths/test/SimpsonIntegration.test.js | 16 +++++++ 2 files changed, 85 insertions(+) create mode 100644 Maths/SimpsonIntegration.js create mode 100644 Maths/test/SimpsonIntegration.test.js diff --git a/Maths/SimpsonIntegration.js b/Maths/SimpsonIntegration.js new file mode 100644 index 0000000000..9a611ad2ba --- /dev/null +++ b/Maths/SimpsonIntegration.js @@ -0,0 +1,69 @@ +/* +* +* @file +* @title Composite Simpson's rule for definite integral evaluation +* @author: [ggkogkou](https://github.com/ggkogkou) +* @brief Calculate definite integrals using composite Simpson's numerical method +* +* @details The idea is to split the interval in an EVEN number N of intervals and use as interpolation points the xi +* for which it applies that xi = x0 + i*h, where h is a step defined as h = (b-a)/N where a and b are the +* first and last points of the interval of the integration [a, b]. +* +* We create a table of the xi and their corresponding f(xi) values and we evaluate the integral by the formula: +* I = h/3 * {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)} +* +* That means that the first and last indexed i f(xi) are multiplied by 1, +* the odd indexed f(xi) by 4 and the even by 2. +* +* N must be even number and a { + if(N%2 === 0) + return true; + return false; + } + if(!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) { throw new TypeError("Expected integer N and finite a, b"); } + if(!isNEven) { throw "N is not an even number"; } + + // Check if a < b + if(a > b) { throw "a must be less or equal than b"; } + if(a === b) return 0; + + // Calculate the step h + const h = (b - a) / N; + + // Find interpolation points + let xi = a; // initialize xi = x0 + let pointsArray = []; + + // Find the sum {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)} + let temp; + for(let i = 0; i < N+1; i++){ + if(i === 0 || i === N) temp = func(xi); + else if(i%2 === 0) temp = 2*func(xi); + else temp = 4*func(xi); + + pointsArray.push(temp); + xi += h; + } + + // Calculate the integral + let result = h/3; + temp = 0; + for(let i=0; i < pointsArray.length; i++) temp += pointsArray[i]; + + result *= temp; + + if (Number.isNaN(result)) { throw "Result is NaN. The input interval doesn't belong to the function's domain"; } + + return result; +} + +export { integralEvaluation } diff --git a/Maths/test/SimpsonIntegration.test.js b/Maths/test/SimpsonIntegration.test.js new file mode 100644 index 0000000000..a713d2f6a1 --- /dev/null +++ b/Maths/test/SimpsonIntegration.test.js @@ -0,0 +1,16 @@ +import { integralEvaluation } from "./SimpsonIntegration"; + +test("Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434", () => { + const result = integralEvaluation(16, 1, 3, (x) => {return Math.sqrt(x);}); + expect(Number(result.toPrecision(7))).toBe(2.797434); +}); + +test("Should return the integral of f(x) = sqrt(x) + x^2 in [1, 3] to be equal 11.46410161", () => { + const result = integralEvaluation(64, 1, 3, (x) => {return Math.sqrt(x) + Math.pow(x, 2);}); + expect(Number(result.toPrecision(10))).toBe(11.46410161); +}); + +test("Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equal 15809.9141543", () => { + const result = integralEvaluation(128, 5, 12, (x) => {return Math.log(x) + Math.PI*Math.pow(x, 3);}); + expect(Number(result.toPrecision(12))).toBe(15809.9141543); +}); From 6ccb15723b03c2c07cc9b011441b3f941daae328 Mon Sep 17 00:00:00 2001 From: ggkogkou Date: Thu, 28 Oct 2021 00:03:56 +0300 Subject: [PATCH 2/6] Minor corrections --- Maths/SimpsonIntegration.js | 9 ++++----- Maths/test/SimpsonIntegration.test.js | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Maths/SimpsonIntegration.js b/Maths/SimpsonIntegration.js index 9a611ad2ba..5987da0493 100644 --- a/Maths/SimpsonIntegration.js +++ b/Maths/SimpsonIntegration.js @@ -24,13 +24,12 @@ function integralEvaluation(N, a, b, func) { // Check if N is an even integer - let isNEven = (N) => { - if(N%2 === 0) - return true; - return false; - } + let isNEven = true; + if(N%2 !== 0) isNEven = false; + if(!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) { throw new TypeError("Expected integer N and finite a, b"); } if(!isNEven) { throw "N is not an even number"; } + if(N <= 0) { throw "N has to be >= 2"; } // Check if a < b if(a > b) { throw "a must be less or equal than b"; } diff --git a/Maths/test/SimpsonIntegration.test.js b/Maths/test/SimpsonIntegration.test.js index a713d2f6a1..b6399435e2 100644 --- a/Maths/test/SimpsonIntegration.test.js +++ b/Maths/test/SimpsonIntegration.test.js @@ -1,4 +1,4 @@ -import { integralEvaluation } from "./SimpsonIntegration"; +import { integralEvaluation } from "../SimpsonIntegration"; test("Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434", () => { const result = integralEvaluation(16, 1, 3, (x) => {return Math.sqrt(x);}); From 4a615a839954f227e2fd3460f010eb6612319a96 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 27 Oct 2021 21:04:54 +0000 Subject: [PATCH 3/6] Auto-update DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index a9d79afade..897e80f19a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -195,6 +195,7 @@ * [ReverseNumber](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ReverseNumber.js) * [ReversePolishNotation](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/ReversePolishNotation.js) * [SieveOfEratosthenes](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SieveOfEratosthenes.js) + * [SimpsonIntegration](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SimpsonIntegration.js) * [Softmax](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/Softmax.js) * [SquareRoot](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SquareRoot.js) * [SumOfDigits](https://github.com/TheAlgorithms/Javascript/blob/master/Maths/SumOfDigits.js) From 1f15216d299c72ee0d0bb1df6a9d24ffb86a6502 Mon Sep 17 00:00:00 2001 From: ggkogkou Date: Thu, 28 Oct 2021 12:02:32 +0300 Subject: [PATCH 4/6] Styled with standard.js --- Maths/SimpsonIntegration.js | 62 +++++++++++++-------------- Maths/test/SimpsonIntegration.test.js | 27 ++++++------ 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/Maths/SimpsonIntegration.js b/Maths/SimpsonIntegration.js index 5987da0493..ecbc7404fe 100644 --- a/Maths/SimpsonIntegration.js +++ b/Maths/SimpsonIntegration.js @@ -22,47 +22,47 @@ */ -function integralEvaluation(N, a, b, func) { - // Check if N is an even integer - let isNEven = true; - if(N%2 !== 0) isNEven = false; +function integralEvaluation (N, a, b, func) { + // Check if N is an even integer + let isNEven = true + if (N % 2 !== 0) isNEven = false - if(!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) { throw new TypeError("Expected integer N and finite a, b"); } - if(!isNEven) { throw "N is not an even number"; } - if(N <= 0) { throw "N has to be >= 2"; } + if (!Number.isInteger(N) || Number.isNaN(a) || Number.isNaN(b)) { throw new TypeError('Expected integer N and finite a, b') } + if (!isNEven) { throw Error('N is not an even number') } + if (N <= 0) { throw Error('N has to be >= 2') } - // Check if a < b - if(a > b) { throw "a must be less or equal than b"; } - if(a === b) return 0; + // Check if a < b + if (a > b) { throw Error('a must be less or equal than b') } + if (a === b) return 0 - // Calculate the step h - const h = (b - a) / N; + // Calculate the step h + const h = (b - a) / N - // Find interpolation points - let xi = a; // initialize xi = x0 - let pointsArray = []; + // Find interpolation points + let xi = a // initialize xi = x0 + const pointsArray = [] - // Find the sum {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)} - let temp; - for(let i = 0; i < N+1; i++){ - if(i === 0 || i === N) temp = func(xi); - else if(i%2 === 0) temp = 2*func(xi); - else temp = 4*func(xi); + // Find the sum {f(x0) + 4*f(x1) + 2*f(x2) + ... + 2*f(xN-2) + 4*f(xN-1) + f(xN)} + let temp + for (let i = 0; i < N + 1; i++) { + if (i === 0 || i === N) temp = func(xi) + else if (i % 2 === 0) temp = 2 * func(xi) + else temp = 4 * func(xi) - pointsArray.push(temp); - xi += h; - } + pointsArray.push(temp) + xi += h + } - // Calculate the integral - let result = h/3; - temp = 0; - for(let i=0; i < pointsArray.length; i++) temp += pointsArray[i]; + // Calculate the integral + let result = h / 3 + temp = 0 + for (let i = 0; i < pointsArray.length; i++) temp += pointsArray[i] - result *= temp; + result *= temp - if (Number.isNaN(result)) { throw "Result is NaN. The input interval doesn't belong to the function's domain"; } + if (Number.isNaN(result)) { throw Error('Result is NaN. The input interval doesnt belong to the functions domain') } - return result; + return result } export { integralEvaluation } diff --git a/Maths/test/SimpsonIntegration.test.js b/Maths/test/SimpsonIntegration.test.js index b6399435e2..b8c3aa2abe 100644 --- a/Maths/test/SimpsonIntegration.test.js +++ b/Maths/test/SimpsonIntegration.test.js @@ -1,16 +1,17 @@ -import { integralEvaluation } from "../SimpsonIntegration"; +import { integralEvaluation } from '../SimpsonIntegration' -test("Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434", () => { - const result = integralEvaluation(16, 1, 3, (x) => {return Math.sqrt(x);}); - expect(Number(result.toPrecision(7))).toBe(2.797434); -}); +test('Should return the integral of f(x) = sqrt(x) in [1, 3] to be equal 2.797434', () => { + const result = integralEvaluation(16, 1, 3, (x) => { return Math.sqrt(x) }) + expect(Number(result.toPrecision(7))).toBe(2.797434) +}) -test("Should return the integral of f(x) = sqrt(x) + x^2 in [1, 3] to be equal 11.46410161", () => { - const result = integralEvaluation(64, 1, 3, (x) => {return Math.sqrt(x) + Math.pow(x, 2);}); - expect(Number(result.toPrecision(10))).toBe(11.46410161); -}); +test('Should return the integral of f(x) = sqrt(x) + x^2 in [1, 3] to be equal 11.46410161', () => { + const result = integralEvaluation(64, 1, 3, (x) => { return Math.sqrt(x) + Math.pow(x, 2) }) + expect(Number(result.toPrecision(10))).toBe(11.46410161) +}) + +test('Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equal 15809.9141543', () => { + const result = integralEvaluation(128, 5, 12, (x) => { return Math.log(x) + Math.PI * Math.pow(x, 3) }) + expect(Number(result.toPrecision(12))).toBe(15809.9141543) +}) -test("Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equal 15809.9141543", () => { - const result = integralEvaluation(128, 5, 12, (x) => {return Math.log(x) + Math.PI*Math.pow(x, 3);}); - expect(Number(result.toPrecision(12))).toBe(15809.9141543); -}); From ffba60c34556f07e6d0e90e8e4b251e6c1cefb62 Mon Sep 17 00:00:00 2001 From: Rak Laptudirm Date: Thu, 28 Oct 2021 14:47:51 +0530 Subject: [PATCH 5/6] chore: remove blank line --- Maths/test/SimpsonIntegration.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Maths/test/SimpsonIntegration.test.js b/Maths/test/SimpsonIntegration.test.js index b8c3aa2abe..c5ebf6a837 100644 --- a/Maths/test/SimpsonIntegration.test.js +++ b/Maths/test/SimpsonIntegration.test.js @@ -14,4 +14,3 @@ test('Should return the integral of f(x) = log(x) + Pi*x^3 in [5, 12] to be equa const result = integralEvaluation(128, 5, 12, (x) => { return Math.log(x) + Math.PI * Math.pow(x, 3) }) expect(Number(result.toPrecision(12))).toBe(15809.9141543) }) - From 445a56d1543e42eb12f94d7666ab3982a78c34d9 Mon Sep 17 00:00:00 2001 From: Rak Laptudirm Date: Thu, 28 Oct 2021 14:50:24 +0530 Subject: [PATCH 6/6] chore: remove blank line --- Maths/SimpsonIntegration.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Maths/SimpsonIntegration.js b/Maths/SimpsonIntegration.js index ecbc7404fe..32ed9c2114 100644 --- a/Maths/SimpsonIntegration.js +++ b/Maths/SimpsonIntegration.js @@ -21,7 +21,6 @@ * */ - function integralEvaluation (N, a, b, func) { // Check if N is an even integer let isNEven = true