|
| 1 | +/// In mathematics, linear interpolation is a method of curve fitting |
| 2 | +/// using linear polynomials to construct new data points within the range of a discrete set of known data points. |
| 3 | +/// Formula: y = y0 + (x - x0) * (y1 - y0) / (x1 - x0) |
| 4 | +/// Source: https://en.wikipedia.org/wiki/Linear_interpolation |
| 5 | +/// point0 and point1 are a tuple containing x and y values we want to interpolate between |
| 6 | +pub fn linear_interpolation(x: f64, point0: (f64, f64), point1: (f64, f64)) -> f64 { |
| 7 | + point0.1 + (x - point0.0) * (point1.1 - point0.1) / (point1.0 - point0.0) |
| 8 | +} |
| 9 | + |
| 10 | +/// In numerical analysis, the Lagrange interpolating polynomial |
| 11 | +/// is the unique polynomial of lowest degree that interpolates a given set of data. |
| 12 | +/// |
| 13 | +/// Source: https://en.wikipedia.org/wiki/Lagrange_polynomial |
| 14 | +/// Source: https://mathworld.wolfram.com/LagrangeInterpolatingPolynomial.html |
| 15 | +/// x is the point we wish to interpolate |
| 16 | +/// defined points are a vector of tuples containing known x and y values of our function |
| 17 | +pub fn lagrange_polynomial_interpolation(x: f64, defined_points: &Vec<(f64, f64)>) -> f64 { |
| 18 | + let mut defined_x_values: Vec<f64> = Vec::new(); |
| 19 | + let mut defined_y_values: Vec<f64> = Vec::new(); |
| 20 | + |
| 21 | + for (x, y) in defined_points { |
| 22 | + defined_x_values.push(*x); |
| 23 | + defined_y_values.push(*y); |
| 24 | + } |
| 25 | + |
| 26 | + let mut sum = 0.0; |
| 27 | + |
| 28 | + for y_index in 0..defined_y_values.len() { |
| 29 | + let mut numerator = 1.0; |
| 30 | + let mut denominator = 1.0; |
| 31 | + for x_index in 0..defined_x_values.len() { |
| 32 | + if y_index == x_index { |
| 33 | + continue; |
| 34 | + } |
| 35 | + denominator *= defined_x_values[y_index] - defined_x_values[x_index]; |
| 36 | + numerator *= x - defined_x_values[x_index]; |
| 37 | + } |
| 38 | + |
| 39 | + sum += numerator / denominator * defined_y_values[y_index]; |
| 40 | + } |
| 41 | + sum |
| 42 | +} |
| 43 | + |
| 44 | +#[cfg(test)] |
| 45 | +mod tests { |
| 46 | + |
| 47 | + use std::assert_eq; |
| 48 | + |
| 49 | + use super::*; |
| 50 | + #[test] |
| 51 | + fn test_linear_intepolation() { |
| 52 | + let point1 = (0.0, 0.0); |
| 53 | + let point2 = (1.0, 1.0); |
| 54 | + let point3 = (2.0, 2.0); |
| 55 | + |
| 56 | + let x1 = 0.5; |
| 57 | + let x2 = 1.5; |
| 58 | + |
| 59 | + let y1 = linear_interpolation(x1, point1, point2); |
| 60 | + let y2 = linear_interpolation(x2, point2, point3); |
| 61 | + |
| 62 | + assert_eq!(y1, x1); |
| 63 | + assert_eq!(y2, x2); |
| 64 | + assert_eq!( |
| 65 | + linear_interpolation(x1, point1, point2), |
| 66 | + linear_interpolation(x1, point2, point1) |
| 67 | + ); |
| 68 | + } |
| 69 | + |
| 70 | + #[test] |
| 71 | + fn test_lagrange_polynomial_interpolation() { |
| 72 | + // defined values for x^2 function |
| 73 | + let defined_points = vec![(0.0, 0.0), (1.0, 1.0), (2.0, 4.0), (3.0, 9.0)]; |
| 74 | + |
| 75 | + // check for equality |
| 76 | + assert_eq!(lagrange_polynomial_interpolation(1.0, &defined_points), 1.0); |
| 77 | + assert_eq!(lagrange_polynomial_interpolation(2.0, &defined_points), 4.0); |
| 78 | + assert_eq!(lagrange_polynomial_interpolation(3.0, &defined_points), 9.0); |
| 79 | + |
| 80 | + //other |
| 81 | + assert_eq!( |
| 82 | + lagrange_polynomial_interpolation(0.5, &defined_points), |
| 83 | + 0.25 |
| 84 | + ); |
| 85 | + assert_eq!( |
| 86 | + lagrange_polynomial_interpolation(2.5, &defined_points), |
| 87 | + 6.25 |
| 88 | + ); |
| 89 | + } |
| 90 | +} |
0 commit comments