1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crateInterpolationError;
/// A trait for bilinear interpolation on 2D data grids.
///
/// # Purpose
/// The `BiLinearInterpolation` trait is designed to perform bilinear interpolation
/// to estimate intermediate values within a grid of 2D points. This method is often
/// used in numerical computation tasks, such as image processing, terrain modeling,
/// and scientific data visualization.
///
/// # Type Parameters
/// - `Point`: The output type, typically used to represent the interpolated 2D point.
/// - `Input`: The input type for the interpolation parameter, typically a scalar value.
///
/// # Associated Type
/// - `Error`: Defines the type returned in case of a failure during interpolation.
///
/// # Method
/// - [`bilinear_interpolate`](#method.bilinear_interpolate):
/// Computes the interpolated value at the given input, returning either the result
/// or an error if the operation cannot proceed.
///
/// # Errors
/// Any errors encountered during interpolation are encapsulated in the type `Error`.
/// This trait is expected to return meaningful errors in cases like:
/// - Insufficient or invalid data for computation.
/// - Inputs that are out of bounds for the given dataset.
/// - Issues specific to the interpolation logic.
///
/// # Example Usage
/// Below is an example demonstrating how an implementing struct might use this trait:
/// ```rust
/// use rust_decimal::Decimal;
/// use optionstratlib_math::curves::Point2D;
/// use optionstratlib_math::error::InterpolationError;
/// use optionstratlib_math::geometrics::BiLinearInterpolation;
/// struct GridInterpolator {
/// // Implementation-specific fields like the grid or data.
/// }
///
/// impl BiLinearInterpolation<Point2D, Decimal> for GridInterpolator {
///
/// fn bilinear_interpolate(&self, x: Decimal) -> Result<Point2D, InterpolationError> {
/// Ok(Point2D::new(x, x)) // Placeholder implementation
/// }
/// }
/// ```
///
/// In this example:
/// - `GridInterpolator` implements the trait for bilinear interpolation.
/// - The `bilinear_interpolate` method calculates the interpolated `Point2D` for a given `x` value.
///
/// # Related Types
/// - [`Point2D`](crate::curves::Point2D): A struct representing a 2D point with `x` and `y` coordinates.
/// - [`CurvesError`](crate::error::CurveError): A recommended error type for detailed error categorization.
///
/// # See Also
/// - [`crate::geometrics::interpolation::InterpolationType`](crate::geometrics::InterpolationType):
/// A module defining different types of interpolation methods.
/// - [`crate::geometrics::interpolation::LinearInterpolation`](crate::geometrics::LinearInterpolation):
/// A simpler interpolation method for one-dimensional data.
///
/// # One point per abscissa
///
/// Every interpolator here reads its sample as a function of the abscissa:
/// at most one ordinate per `x`. See
/// [`Curve::new`](crate::curves::Curve::new) for the rule and for why no
/// constructor enforces it. A sample carrying several ordinates at one
/// abscissa is outside the contract: the grid cell around a repeated
/// abscissa has zero width and the slope across it is undefined, so the
/// answer is [`InterpolationError::DegenerateInterval`].
///
/// That holds on every branch, including the exact match: the
/// [`Curve`](crate::curves::Curve) implementation short-circuits an `x` that
/// lands on a sample, and on a stack of ordinates at that `x` it reports the
/// degeneracy rather than returning the lowest of them.
///
/// A projection of a surface is multi-valued by construction, which is why
/// [`Surface::project_onto`](crate::surfaces::Surface::project_onto) returns a
/// `Vec<Point2D>` and not a curve; aggregate it before interpolating.
///
/// # Cells at the edge of the sample
///
/// A cell wants samples on both sides of the query along every axis, which
/// the samples at the upper edge of the domain cannot supply. The
/// [`Curve`](crate::curves::Curve) implementation builds its cell out of two
/// consecutive segments and clamps the far one to the curve's last segment
/// where it would run off the end, so the segment holding the query is
/// always one edge of the cell and the answer stays a convex combination of
/// the four ordinates read; that implementation documents the rule and its
/// consequences in full. The [`Surface`](crate::surfaces::Surface) one picks
/// the four samples nearest the query, so its cell has no end to run off.