Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/main/java/com/thealgorithms/maths/Neville.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
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 of
* degree at most n that passes through all the points. Neville's algorithm
* computes the value of this polynomial at a given point.
*
* <p>
* 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, 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) {
throw new IllegalArgumentException("x and y arrays must have the same length.");
}
if (x.length == 0) {
throw new IllegalArgumentException("Input arrays cannot be empty.");
}

// Check for duplicate x-coordinates to prevent division by zero
Set<Double> 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

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];
}
}
69 changes: 69 additions & 0 deletions src/test/java/com/thealgorithms/maths/NevilleTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
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));
}

@Test
public void testDuplicateXCoordinates() {
double[] x = {1, 2, 1};
double[] y = {5, 8, 3};
double target = 1.5;
assertThrows(IllegalArgumentException.class, () -> Neville.interpolate(x, y, target));
}
}