mirror of
https://codeberg.org/LibrEDA/interp
synced 2026-05-31 01:06:36 +08:00
Relax trait bounds.
This commit is contained in:
102
src/interp2d.rs
102
src/interp2d.rs
@@ -27,7 +27,7 @@
|
||||
use crate::find_closest_neighbours_indices;
|
||||
use ndarray::{ArrayBase, Axis, Data, Ix2, OwnedRepr};
|
||||
use num_traits::Num;
|
||||
use std::ops::Mul;
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
// /// Define the extrapolation behaviour when a point outside of the sample grid should
|
||||
// /// be evaluated.
|
||||
@@ -88,12 +88,12 @@ where
|
||||
/// the value is *extrapolated*.
|
||||
fn interpolate2d_bilinear<C, Z>(x00: Z, x10: Z, x01: Z, x11: Z, alpha: C, beta: C) -> Z
|
||||
where
|
||||
C: Num + Copy + Mul<Z, Output = Z> + PartialOrd,
|
||||
Z: Num + Copy + Mul<C, Output = Z>,
|
||||
C: Copy + Add<Output = C> + Sub<Output = C>,
|
||||
Z: Copy + Mul<C, Output = Z> + Add<Output = Z> + Sub<Output = Z>,
|
||||
{
|
||||
// debug_assert!(alpha >= C::zero() && alpha <= C::one(), "Cannot extrapolate.");
|
||||
// debug_assert!(beta >= C::zero() && beta <= C::one(), "Cannot extrapolate.");
|
||||
x00 + alpha * (x10 - x00) + beta * (x01 - x00) + alpha * beta * (x00 + x11 - x10 - x01)
|
||||
x00 + (x10 - x00) * alpha + (x01 - x00) * beta + (x00 + x11 - x10 - x01) * alpha * beta
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -117,8 +117,9 @@ fn interp2d<C, Z>(
|
||||
(v00, v10, v01, v11): (Z, Z, Z, Z),
|
||||
) -> Z
|
||||
where
|
||||
C: Num + Copy + Mul<Z, Output = Z> + PartialOrd,
|
||||
Z: Num + Copy + Mul<C, Output = Z>,
|
||||
C: Copy + Sub<Output = C> + Div,
|
||||
Z: Copy + Mul<<C as Div>::Output, Output = Z> + Add<Output = Z> + Sub<Output = Z>,
|
||||
<C as Div>::Output: Copy + Num,
|
||||
{
|
||||
let dx = x1 - x0;
|
||||
let dy = y1 - y0;
|
||||
@@ -131,7 +132,6 @@ where
|
||||
|
||||
impl<C, Z, S> Interp2D<C, Z, S>
|
||||
where
|
||||
C: Num + Copy + PartialOrd,
|
||||
S: Data<Elem = Z>,
|
||||
{
|
||||
/// Create a new interpolation engine.
|
||||
@@ -148,7 +148,10 @@ where
|
||||
/// * dimensions of x/y axis and z-values don't match.
|
||||
/// * one axis is empty.
|
||||
/// * `x` and `y` values are not monotonic.
|
||||
pub fn new(x: Vec<C>, y: Vec<C>, z: ArrayBase<S, Ix2>) -> Self {
|
||||
pub fn new(x: Vec<C>, y: Vec<C>, z: ArrayBase<S, Ix2>) -> Self
|
||||
where
|
||||
C: PartialOrd,
|
||||
{
|
||||
assert_eq!(z.len_of(Axis(0)), x.len(), "x-axis length mismatch.");
|
||||
assert_eq!(z.len_of(Axis(1)), y.len(), "y-axis length mismatch.");
|
||||
assert!(!x.is_empty());
|
||||
@@ -174,12 +177,56 @@ where
|
||||
|
||||
Self { x, y, z }
|
||||
}
|
||||
/// Get the boundaries of the sample range
|
||||
/// as `((x0, x1), (y0, y1))` tuple.
|
||||
pub fn bounds(&self) -> ((C, C), (C, C))
|
||||
where
|
||||
C: Copy,
|
||||
{
|
||||
(
|
||||
(self.x[0], self.x[self.x.len() - 1]),
|
||||
(self.y[0], self.y[self.y.len() - 1]),
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if the `(x, y)` coordinate lies within the defined sample range.
|
||||
pub fn is_within_bounds(&self, (x, y): (C, C)) -> bool
|
||||
where
|
||||
C: PartialOrd + Copy,
|
||||
{
|
||||
let ((x0, x1), (y0, y1)) = self.bounds();
|
||||
x0 <= x && x <= x1 && y0 <= y && y <= y1
|
||||
}
|
||||
|
||||
/// Get the x-coordinate values.
|
||||
pub fn xs(&self) -> &Vec<C> {
|
||||
&self.x
|
||||
}
|
||||
|
||||
/// Get the y-coordinate values.
|
||||
pub fn ys(&self) -> &Vec<C> {
|
||||
&self.y
|
||||
}
|
||||
|
||||
/// Get the raw z values.
|
||||
pub fn z(&self) -> &ArrayBase<S, Ix2> {
|
||||
&self.z
|
||||
}
|
||||
|
||||
/// Create a new interpolated table by applying a function elementwise to the values.
|
||||
pub fn map_values<Z2>(&self, f: impl Fn(&Z) -> Z2) -> Interp2D<C, Z2, OwnedRepr<Z2>>
|
||||
where
|
||||
C: PartialOrd + Clone,
|
||||
{
|
||||
Interp2D::new(self.x.clone(), self.y.clone(), self.z.map(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, Z, S> Interp2D<C, Z, S>
|
||||
where
|
||||
C: Num + Copy + Mul<Z, Output = Z> + PartialOrd,
|
||||
Z: Num + Copy + Mul<C, Output = Z>,
|
||||
C: Copy + Sub<Output = C> + Div + PartialOrd,
|
||||
Z: Copy + Mul<<C as Div>::Output, Output = Z> + Add<Output = Z> + Sub<Output = Z>,
|
||||
<C as Div>::Output: Copy + Num,
|
||||
S: Data<Elem = Z> + Clone,
|
||||
{
|
||||
/// Evaluate the sampled function by interpolation at `(x, y)`.
|
||||
@@ -213,41 +260,6 @@ where
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the boundaries of the sample range
|
||||
/// as `((x0, x1), (y0, y1))` tuple.
|
||||
pub fn bounds(&self) -> ((C, C), (C, C)) {
|
||||
(
|
||||
(self.x[0], self.x[self.x.len() - 1]),
|
||||
(self.y[0], self.y[self.y.len() - 1]),
|
||||
)
|
||||
}
|
||||
|
||||
/// Check if the `(x, y)` coordinate lies within the defined sample range.
|
||||
pub fn is_within_bounds(&self, (x, y): (C, C)) -> bool {
|
||||
let ((x0, x1), (y0, y1)) = self.bounds();
|
||||
x0 <= x && x <= x1 && y0 <= y && y <= y1
|
||||
}
|
||||
|
||||
/// Get the x-coordinate values.
|
||||
pub fn xs(&self) -> &Vec<C> {
|
||||
&self.x
|
||||
}
|
||||
|
||||
/// Get the y-coordinate values.
|
||||
pub fn ys(&self) -> &Vec<C> {
|
||||
&self.y
|
||||
}
|
||||
|
||||
/// Get the raw z values.
|
||||
pub fn z(&self) -> &ArrayBase<S, Ix2> {
|
||||
&self.z
|
||||
}
|
||||
|
||||
/// Create a new interpolated table by applying a function elementwise to the values.
|
||||
pub fn map_values<Z2>(&self, f: impl Fn(&Z) -> Z2) -> Interp2D<C, Z2, OwnedRepr<Z2>> {
|
||||
Interp2D::new(self.x.clone(), self.y.clone(), self.z.map(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, Z, S> Interp2D<C, Z, S>
|
||||
|
||||
Reference in New Issue
Block a user