From e6cf4b08a335c7381c923d3428503ca3024d71ad Mon Sep 17 00:00:00 2001 From: KeyKyrios Date: Mon, 20 Oct 2025 03:36:19 +0530 Subject: [PATCH 1/8] feat: Add Neville's algorithm for polynomial interpolation --- .../java/com/thealgorithms/maths/Neville.java | 49 ++++++++++++++ .../com/thealgorithms/maths/NevilleTest.java | 65 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/Neville.java create mode 100644 src/test/java/com/thealgorithms/maths/NevilleTest.java diff --git a/src/main/java/com/thealgorithms/maths/Neville.java b/src/main/java/com/thealgorithms/maths/Neville.java new file mode 100644 index 000000000000..9fe041376484 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/Neville.java @@ -0,0 +1,49 @@ +Neville.java +package com.thealgorithms.maths; + +/** + * In numerical analysis, Neville's algorithm is an algorithm used for + * polynomial interpolation. Given n+1 points, there is a unique polynomial + * of degree at most n that passes through all the points. Neville's + * algorithm computes the value of this polynomial at a given point. + * + *

+ * Wikipedia: https://en.wikipedia.org/wiki/Neville%27s_algorithm + * + * @author Mitrajit Ghorui(KeyKyrios) + */ +public final class Neville { + private Neville() { + } + + /** + * Evaluates the polynomial that passes through the given points at a specific x-coordinate. + * + * @param x The x-coordinates of the points. Must be the same length as y. + * @param y The y-coordinates of the points. Must be the same length as x. + * @param target The x-coordinate at which to evaluate the polynomial. + * @return The interpolated y-value at the target x-coordinate. + * @throws IllegalArgumentException if the lengths of x and y arrays are different, + * or if the arrays are empty. + */ + public static double interpolate(double[] x, double[] y, double target) { + if (x.length != y.length) { + throw new IllegalArgumentException("x and y arrays must have the same length."); + } + if (x.length == 0) { + throw new IllegalArgumentException("Input arrays cannot be empty."); + } + + int n = x.length; + double[] p = new double[n]; + System.arraycopy(y, 0, p, 0, n); // Initialize p with y values + + for (int k = 1; k < n; k++) { + for (int i = 0; i < n - k; i++) { + p[i] = ((target - x[i + k]) * p[i] + (x[i] - target) * p[i + 1]) / (x[i] - x[i + k]); + } + } + + return p[0]; + } +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/maths/NevilleTest.java b/src/test/java/com/thealgorithms/maths/NevilleTest.java new file mode 100644 index 000000000000..1763cbcb1df0 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/NevilleTest.java @@ -0,0 +1,65 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +public class NevilleTest { + + @Test + public void testInterpolateLinear() { + // Test with a simple linear function y = 2x + 1 + // Points (0, 1) and (2, 5) + double[] x = {0, 2}; + double[] y = {1, 5}; + // We want to find y when x = 1, which should be 3 + double target = 1; + double expected = 3.0; + assertEquals(expected, Neville.interpolate(x, y, target), 1e-9); + } + + @Test + public void testInterpolateQuadratic() { + // Test with a quadratic function y = x^2 + // Points (0, 0), (1, 1), (3, 9) + double[] x = {0, 1, 3}; + double[] y = {0, 1, 9}; + // We want to find y when x = 2, which should be 4 + double target = 2; + double expected = 4.0; + assertEquals(expected, Neville.interpolate(x, y, target), 1e-9); + } + + @Test + public void testInterpolateWithNegativeNumbers() { + // Test with y = x^2 - 2x + 1 + // Points (-1, 4), (0, 1), (2, 1) + double[] x = {-1, 0, 2}; + double[] y = {4, 1, 1}; + // We want to find y when x = 1, which should be 0 + double target = 1; + double expected = 0.0; + assertEquals(expected, Neville.interpolate(x, y, target), 1e-9); + } + + @Test + public void testMismatchedArrayLengths() { + double[] x = {1, 2}; + double[] y = {1}; + double target = 1.5; + assertThrows(IllegalArgumentException.class, () -> { + Neville.interpolate(x, y, target); + }); + } + + @Test + public void testEmptyArrays() { + double[] x = {}; + double[] y = {}; + double target = 1; + assertThrows(IllegalArgumentException.class, () -> { + Neville.interpolate(x, y, target); + }); + } +} \ No newline at end of file From 8176ae15b8d9ab4a37d7d9290fc644db0ba187e7 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 03:47:05 +0530 Subject: [PATCH 2/8] Update Neville.java --- src/main/java/com/thealgorithms/maths/Neville.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Neville.java b/src/main/java/com/thealgorithms/maths/Neville.java index 9fe041376484..16d57cba62c2 100644 --- a/src/main/java/com/thealgorithms/maths/Neville.java +++ b/src/main/java/com/thealgorithms/maths/Neville.java @@ -1,4 +1,3 @@ -Neville.java package com.thealgorithms.maths; /** @@ -46,4 +45,4 @@ public static double interpolate(double[] x, double[] y, double target) { return p[0]; } -} \ No newline at end of file +} From f11b7149f0225c55b2008d5884e4f50aeeb0f996 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 04:17:56 +0530 Subject: [PATCH 3/8] style: Fix linter formatting issues. --- src/test/java/com/thealgorithms/maths/NevilleTest.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/NevilleTest.java b/src/test/java/com/thealgorithms/maths/NevilleTest.java index 1763cbcb1df0..1b19fd413c1f 100644 --- a/src/test/java/com/thealgorithms/maths/NevilleTest.java +++ b/src/test/java/com/thealgorithms/maths/NevilleTest.java @@ -48,9 +48,7 @@ public void testMismatchedArrayLengths() { double[] x = {1, 2}; double[] y = {1}; double target = 1.5; - assertThrows(IllegalArgumentException.class, () -> { - Neville.interpolate(x, y, target); - }); + assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target)); } @Test @@ -58,8 +56,6 @@ public void testEmptyArrays() { double[] x = {}; double[] y = {}; double target = 1; - assertThrows(IllegalArgumentException.class, () -> { - Neville.interpolate(x, y, target); - }); + assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target)); } -} \ No newline at end of file +} From fd54a19130d8200b85548b02d4e0f822de4c9db3 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:15:40 +0530 Subject: [PATCH 4/8] Handled Div by Zero Case --- src/main/java/com/thealgorithms/maths/Neville.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/maths/Neville.java b/src/main/java/com/thealgorithms/maths/Neville.java index 16d57cba62c2..f8ab4bd74b01 100644 --- a/src/main/java/com/thealgorithms/maths/Neville.java +++ b/src/main/java/com/thealgorithms/maths/Neville.java @@ -1,5 +1,9 @@ +// Neville.java package com.thealgorithms.maths; +import java.util.HashSet; +import java.util.Set; + /** * In numerical analysis, Neville's algorithm is an algorithm used for * polynomial interpolation. Given n+1 points, there is a unique polynomial @@ -23,7 +27,7 @@ private Neville() { * @param target The x-coordinate at which to evaluate the polynomial. * @return The interpolated y-value at the target x-coordinate. * @throws IllegalArgumentException if the lengths of x and y arrays are different, - * or if the arrays are empty. + * if the arrays are empty, or if x-coordinates are not unique. */ public static double interpolate(double[] x, double[] y, double target) { if (x.length != y.length) { @@ -33,6 +37,13 @@ public static double interpolate(double[] x, double[] y, double target) { throw new IllegalArgumentException("Input arrays cannot be empty."); } + Set seenX = new HashSet<>(); + for (double val : x) { + if (!seenX.add(val)) { + throw new IllegalArgumentException("Input x-coordinates must be unique."); + } + } + int n = x.length; double[] p = new double[n]; System.arraycopy(y, 0, p, 0, n); // Initialize p with y values From 32dde851aa35197fd89af196fefe215d774c7cd8 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:16:56 +0530 Subject: [PATCH 5/8] Update NevilleTest.java --- src/test/java/com/thealgorithms/maths/NevilleTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/com/thealgorithms/maths/NevilleTest.java b/src/test/java/com/thealgorithms/maths/NevilleTest.java index 1b19fd413c1f..252367cd7000 100644 --- a/src/test/java/com/thealgorithms/maths/NevilleTest.java +++ b/src/test/java/com/thealgorithms/maths/NevilleTest.java @@ -58,4 +58,12 @@ public void testEmptyArrays() { double target = 1; assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target)); } + + @Test + public void testDuplicateXCoordinatesThrowsException() { + double[] x = {1, 2, 1}; + double[] y = {5, 8, 3}; + double target = 1.5; + assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target)); + } } From f38c3212fd5f85fb1b6012be4ad78b2cd0739538 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:17:35 +0530 Subject: [PATCH 6/8] Update Neville.java --- src/main/java/com/thealgorithms/maths/Neville.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/maths/Neville.java b/src/main/java/com/thealgorithms/maths/Neville.java index f8ab4bd74b01..e2b4860c73ea 100644 --- a/src/main/java/com/thealgorithms/maths/Neville.java +++ b/src/main/java/com/thealgorithms/maths/Neville.java @@ -1,4 +1,3 @@ -// Neville.java package com.thealgorithms.maths; import java.util.HashSet; From 7bca717a95a1b8d9da20d4b4c18aaf6dc5c9fbb7 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:29:17 +0530 Subject: [PATCH 7/8] Update NevilleTest.java --- src/test/java/com/thealgorithms/maths/NevilleTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/maths/NevilleTest.java b/src/test/java/com/thealgorithms/maths/NevilleTest.java index 252367cd7000..234fb2d65ce4 100644 --- a/src/test/java/com/thealgorithms/maths/NevilleTest.java +++ b/src/test/java/com/thealgorithms/maths/NevilleTest.java @@ -58,9 +58,9 @@ public void testEmptyArrays() { double target = 1; assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target)); } - + @Test - public void testDuplicateXCoordinatesThrowsException() { + public void testDuplicateXCoordinates() { double[] x = {1, 2, 1}; double[] y = {5, 8, 3}; double target = 1.5; From 8a7cd76a5c40f15cad1c2f06c0273babe9cd8eb8 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:44:04 +0530 Subject: [PATCH 8/8] Update Neville.java --- .../java/com/thealgorithms/maths/Neville.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/thealgorithms/maths/Neville.java b/src/main/java/com/thealgorithms/maths/Neville.java index e2b4860c73ea..ca45f2e8a042 100644 --- a/src/main/java/com/thealgorithms/maths/Neville.java +++ b/src/main/java/com/thealgorithms/maths/Neville.java @@ -5,9 +5,9 @@ /** * In numerical analysis, Neville's algorithm is an algorithm used for - * polynomial interpolation. Given n+1 points, there is a unique polynomial - * of degree at most n that passes through all the points. Neville's - * algorithm computes the value of this polynomial at a given point. + * polynomial interpolation. Given n+1 points, there is a unique polynomial of + * degree at most n that passes through all the points. Neville's algorithm + * computes the value of this polynomial at a given point. * *

* Wikipedia: https://en.wikipedia.org/wiki/Neville%27s_algorithm @@ -15,18 +15,20 @@ * @author Mitrajit Ghorui(KeyKyrios) */ public final class Neville { + private Neville() { } /** - * Evaluates the polynomial that passes through the given points at a specific x-coordinate. + * Evaluates the polynomial that passes through the given points at a + * specific x-coordinate. * * @param x The x-coordinates of the points. Must be the same length as y. * @param y The y-coordinates of the points. Must be the same length as x. * @param target The x-coordinate at which to evaluate the polynomial. * @return The interpolated y-value at the target x-coordinate. - * @throws IllegalArgumentException if the lengths of x and y arrays are different, - * if the arrays are empty, or if x-coordinates are not unique. + * @throws IllegalArgumentException if the lengths of x and y arrays are + * different, if the arrays are empty, or if x-coordinates are not unique. */ public static double interpolate(double[] x, double[] y, double target) { if (x.length != y.length) { @@ -36,6 +38,7 @@ public static double interpolate(double[] x, double[] y, double target) { throw new IllegalArgumentException("Input arrays cannot be empty."); } + // Check for duplicate x-coordinates to prevent division by zero Set seenX = new HashSet<>(); for (double val : x) { if (!seenX.add(val)) {