From 49e6435446d36d21dcf5f149dac7208c3c812c8c Mon Sep 17 00:00:00 2001 From: KeyKyrios Date: Mon, 20 Oct 2025 14:24:50 +0530 Subject: [PATCH 1/2] feat(numerical_methods): Add Neville's algorithm for interpolation --- numerical_methods/nevilles_algorithm.c | 85 ++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 numerical_methods/nevilles_algorithm.c diff --git a/numerical_methods/nevilles_algorithm.c b/numerical_methods/nevilles_algorithm.c new file mode 100644 index 0000000000..a6e2b323f6 --- /dev/null +++ b/numerical_methods/nevilles_algorithm.c @@ -0,0 +1,85 @@ +/** + * @file + * @brief Implementation of Neville's Algorithm for polynomial interpolation. + * @details Neville's algorithm is an iterative method to find the value of a + * polynomial that passes through a given set of n+1 points. + * https://en.wikipedia.org/wiki/Neville%27s_algorithm + * @author [Mitrajit Ghorui](https://github.com/KeyKyrios) + */ +#include /// for assert +#include /// for fabs +#include /// for IO operations +#include /// for malloc, free +#include /// for memcpy + +/** + * @brief Evaluates the interpolating polynomial at a specific point. + * @param x_coords Array of x-coordinates of the given points. + * @param y_coords Array of y-coordinates of the given points. + * @param n The number of points (size of the arrays). + * @param target The x-coordinate at which to evaluate the polynomial. + * @returns The interpolated y-value at the target x-coordinate. Returns NaN if + * inputs are invalid. + */ +double interpolate(const double *x_coords, const double *y_coords, size_t n, + double target) { + if (n == 0) { + return NAN; // Not a Number, indicates error + } + + double *p = (double *)malloc(n * sizeof(double)); + if (p == NULL) { + return NAN; // Memory allocation failed + } + memcpy(p, y_coords, n * sizeof(double)); + + for (size_t k = 1; k < n; ++k) { + for (size_t i = 0; i < n - k; ++i) { + p[i] = ((target - x_coords[i + k]) * p[i] + + (x_coords[i] - target) * p[i + 1]) / + (x_coords[i] - x_coords[i + k]); + } + } + + double result = p[0]; + free(p); + return result; +} + +/** + * @brief Self-test implementations + * @returns void + */ +static void tests() { + // Test 1: Linear interpolation y = 2x + 1 + double x1[] = {0, 2}; + double y1[] = {1, 5}; + double expected1 = 3.0; + assert(fabs(interpolate(x1, y1, 2, 1.0) - expected1) < 1e-9); + printf("Linear test passed.\n"); + + // Test 2: Quadratic interpolation y = x^2 + double x2[] = {0, 1, 3}; + double y2[] = {0, 1, 9}; + double expected2 = 4.0; + assert(fabs(interpolate(x2, y2, 3, 2.0) - expected2) < 1e-9); + printf("Quadratic test passed.\n"); + + // Test 3: Negative numbers y = x^2 - 2x + 1 + double x3[] = {-1, 0, 2}; + double y3[] = {4, 1, 1}; + double expected3 = 0.0; + assert(fabs(interpolate(x3, y3, 3, 1.0) - expected3) < 1e-9); + printf("Negative numbers test passed.\n"); + + printf("All tests have successfully passed!\n"); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + tests(); // run self-test implementations + return 0; +} \ No newline at end of file From d7795f8d8cb7e603e5d584a59c8c36f62073b9e9 Mon Sep 17 00:00:00 2001 From: Keykyrios Date: Mon, 20 Oct 2025 15:21:15 +0530 Subject: [PATCH 2/2] Handled Div. by zero case --- numerical_methods/nevilles_algorithm.c | 35 ++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/numerical_methods/nevilles_algorithm.c b/numerical_methods/nevilles_algorithm.c index a6e2b323f6..50ff7f6ea9 100644 --- a/numerical_methods/nevilles_algorithm.c +++ b/numerical_methods/nevilles_algorithm.c @@ -6,11 +6,12 @@ * https://en.wikipedia.org/wiki/Neville%27s_algorithm * @author [Mitrajit Ghorui](https://github.com/KeyKyrios) */ -#include /// for assert -#include /// for fabs -#include /// for IO operations -#include /// for malloc, free -#include /// for memcpy +#include /// for assert +#include /// for fabs and isnan +#include /// for bool +#include /// for IO operations +#include /// for malloc, free +#include /// for memcpy /** * @brief Evaluates the interpolating polynomial at a specific point. @@ -18,18 +19,26 @@ * @param y_coords Array of y-coordinates of the given points. * @param n The number of points (size of the arrays). * @param target The x-coordinate at which to evaluate the polynomial. - * @returns The interpolated y-value at the target x-coordinate. Returns NaN if - * inputs are invalid. + * @returns The interpolated y-value. Returns NaN if inputs are invalid or + * x-coordinates are not unique. */ double interpolate(const double *x_coords, const double *y_coords, size_t n, double target) { if (n == 0) { - return NAN; // Not a Number, indicates error + return NAN; + } + + for (size_t i = 0; i < n; ++i) { + for (size_t j = i + 1; j < n; ++j) { + if (x_coords[i] == x_coords[j]) { + return NAN; // Duplicate x-values are invalid + } + } } double *p = (double *)malloc(n * sizeof(double)); if (p == NULL) { - return NAN; // Memory allocation failed + return NAN; // Memory allocation failed } memcpy(p, y_coords, n * sizeof(double)); @@ -72,6 +81,12 @@ static void tests() { assert(fabs(interpolate(x3, y3, 3, 1.0) - expected3) < 1e-9); printf("Negative numbers test passed.\n"); + // Test 4: Duplicate x-coordinates should return NaN + double x4[] = {1, 2, 1}; + double y4[] = {5, 8, 3}; + assert(isnan(interpolate(x4, y4, 3, 1.5))); + printf("Duplicate X coordinate test passed.\n"); + printf("All tests have successfully passed!\n"); } @@ -82,4 +97,4 @@ static void tests() { int main() { tests(); // run self-test implementations return 0; -} \ No newline at end of file +}