Relax trait bounds.

This commit is contained in:
Thomas Kramer
2023-06-06 08:37:19 +02:00
parent ce90534cc0
commit fddbcfa06a

View File

@@ -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>