Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default to bilinear interpolation #6

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ logarithmic spaced values.
- added type aliases for common interpolators
- make the `VectorExtensions` trait public
- add `Interp1D::new_unchecked` and `Interp2D::new_unchecked` methods
- add biliniar extrapolation
- add bilinear extrapolation
- impl `Default` for interpolation strategies

# 0.3.0
- add 2d interpolation
- add biliniar interpolation strategy
- add bilinear interpolation strategy
- rename `Strategy` to `Interp1DStrategy` and `StrategyBuilder` to `Interp1DStrategyBuilder`
- make extrapolate filed of `Linear` private add `extrapolate(bool)` method instead.

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ license = "MIT"
description = "Interpolation package for ndarray"
repository = "https://github.com/jonasBoss/ndarray-interp"

keywords = ["interpolation", "multidimensional", "liniar", "biliniar", "cubic-spline"]
keywords = ["interpolation", "multidimensional", "linear", "bilinear", "cubic-spline"]
categories = ["science", "algorithms", "mathematics"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ A Interpolation crate for usage with the rust [ndarray](https://crates.io/crates
## Interpolation strategies
- Linear interpolation with, and without extrapolation
- Cubic spline interpolation [Wikipedia](https://en.wikipedia.org/wiki/Spline_interpolation)
- Biliniar interpolation with, and without extrapolation [Wikipedia](https://en.wikipedia.org/wiki/Bilinear_interpolation)
- Bilinear interpolation with, and without extrapolation [Wikipedia](https://en.wikipedia.org/wiki/Bilinear_interpolation)

## Planned Features
- More interpolation strategies
Expand Down
4 changes: 2 additions & 2 deletions benches/bench_interp2d_query_dim.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use ndarray::{Array, Array1, Axis};
use ndarray_interp::interp2d::{Biliniar, Interp2D, Interp2DScalar};
use ndarray_interp::interp2d::{Bilinear, Interp2D, Interp2DScalar};

use rand_extensions::RandArray;

mod rand_extensions;

fn setup() -> (Interp2DScalar<f64, Biliniar>, Array1<f64>, Array1<f64>) {
fn setup() -> (Interp2DScalar<f64, Bilinear>, Array1<f64>, Array1<f64>) {
let data = Array::from_rand(10_000, (0.0, 1.0), 42)
.into_shape((100, 100))
.unwrap();
Expand Down
14 changes: 7 additions & 7 deletions src/interp2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! - [`Interp2DStrategyBuilder`] The trait used to specialize [`Interp2DBuilder`] to initialize the correct strategy
//!
//! # Strategies
//! - [`Biliniar`] Linear interpolation strategy
//! - [`Bilinear`] Linear interpolation strategy

use std::{any::TypeId, fmt::Debug, ops::Sub};

Expand All @@ -29,7 +29,7 @@ use crate::{
mod aliases;
mod strategies;
pub use aliases::*;
pub use strategies::{Biliniar, Interp2DStrategy, Interp2DStrategyBuilder};
pub use strategies::{Bilinear, Interp2DStrategy, Interp2DStrategyBuilder};

/// Two dimensional interpolator
#[derive(Debug)]
Expand All @@ -47,7 +47,7 @@ where
strategy: Strat,
}

impl<Sd, D> Interp2D<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Biliniar>
impl<Sd, D> Interp2D<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Bilinear>
where
Sd: Data,
Sd::Elem: Num + PartialOrd + NumCast + Copy + Debug + Sub + Send,
Expand All @@ -56,7 +56,7 @@ where
/// Get the [Interp2DBuilder]
pub fn builder(
data: ArrayBase<Sd, D>,
) -> Interp2DBuilder<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Biliniar> {
) -> Interp2DBuilder<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Bilinear> {
Interp2DBuilder::new(data)
}
}
Expand Down Expand Up @@ -379,7 +379,7 @@ where
strategy: Strat,
}

impl<Sd, D> Interp2DBuilder<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Biliniar>
impl<Sd, D> Interp2DBuilder<Sd, OwnedRepr<Sd::Elem>, OwnedRepr<Sd::Elem>, D, Bilinear>
where
Sd: Data,
Sd::Elem: Num + PartialOrd + NumCast + Copy + Debug + Sub,
Expand All @@ -400,7 +400,7 @@ where
x,
y,
data,
strategy: Biliniar::new(),
strategy: Bilinear::new(),
}
}
}
Expand All @@ -416,7 +416,7 @@ where
Strat: Interp2DStrategyBuilder<Sd, Sx, Sy, D>,
{
/// Set the interpolation strategy by provideing a [`Interp2DStrategyBuilder`].
/// By default [`Biliniar`] is used.
/// By default [`Bilinear`] is used.
pub fn strategy<NewStrat: Interp2DStrategyBuilder<Sd, Sx, Sy, D>>(
self,
strategy: NewStrat,
Expand Down
4 changes: 2 additions & 2 deletions src/interp2d/strategies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use crate::{BuilderError, InterpolateError};

use super::Interp2D;

mod biliniar;
mod bilinear;

pub use biliniar::Biliniar;
pub use bilinear::Bilinear;

pub trait Interp2DStrategyBuilder<Sd, Sx, Sy, D>
where
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
use std::{fmt::Debug, ops::Sub};

use ndarray::{Data, Dimension, RemoveAxis, Zip};
use ndarray::{Data, Dimension, RemoveAxis, Zip, RawData};
use num_traits::{Num, NumCast};

use crate::{interp1d::Linear, InterpolateError};

use super::{Interp2DStrategy, Interp2DStrategyBuilder};

#[derive(Debug)]
pub struct Biliniar {
pub struct Bilinear {
extrapolate: bool,
allow_default: bool
}

impl<Sd, Sx, Sy, D> Interp2DStrategyBuilder<Sd, Sx, Sy, D> for Biliniar
impl<Sd, Sx, Sy, D> Interp2DStrategyBuilder<Sd, Sx, Sy, D> for Bilinear
where
Sd: Data,
Sd::Elem: Num + PartialOrd + NumCast + Copy + Debug + Sub + Send,
Sx: Data<Elem = Sd::Elem>,
Sy: Data<Elem = Sd::Elem>,
D: Dimension + RemoveAxis,
D::Smaller: RemoveAxis,
<Sd as RawData>::Elem: Default
{
const MINIMUM_DATA_LENGHT: usize = 2;

Expand All @@ -35,14 +37,15 @@ where
}
}

impl<Sd, Sx, Sy, D> Interp2DStrategy<Sd, Sx, Sy, D> for Biliniar
impl<Sd, Sx, Sy, D> Interp2DStrategy<Sd, Sx, Sy, D> for Bilinear
where
Sd: Data,
Sd::Elem: Num + PartialOrd + NumCast + Copy + Debug + Sub + Send,
Sx: Data<Elem = Sd::Elem>,
Sy: Data<Elem = Sd::Elem>,
D: Dimension + RemoveAxis,
D::Smaller: RemoveAxis,
<Sd as RawData>::Elem: Default
{
fn interp_into(
&self,
Expand All @@ -51,17 +54,29 @@ where
x: <Sx>::Elem,
y: <Sy>::Elem,
) -> Result<(), crate::InterpolateError> {
if !self.extrapolate && !interpolator.is_in_x_range(x) {
if self.extrapolate && self.allow_default {
return Err(InterpolateError::InvalidArguments(format!(
"cannot extrapolate if default is allowed"
)));
}
if !self.extrapolate && !interpolator.is_in_x_range(x) && !self.allow_default {
return Err(InterpolateError::OutOfBounds(format!(
"x = {x:?} is not in range"
)));
}
if !self.extrapolate && !interpolator.is_in_y_range(y) {
if !self.extrapolate && !interpolator.is_in_y_range(y) && !self.allow_default {
return Err(InterpolateError::OutOfBounds(format!(
"y = {y:?} is not in range"
)));
}

// If out of bounds and allow_default, return default
if self.allow_default && (!interpolator.is_in_x_range(x) || !interpolator.is_in_y_range(y)) {
target.into_iter().for_each(|z| *z = Default::default());
return Ok(());
}

// Otherwise, blend values...
let (x_idx, y_idx) = interpolator.get_index_left_of(x, y);
let (x1, y1, z11) = interpolator.index_point(x_idx, y_idx);
let (_, _, z12) = interpolator.index_point(x_idx, y_idx + 1);
Expand All @@ -82,18 +97,23 @@ where
}
}

impl Biliniar {
impl Bilinear {
pub fn new() -> Self {
Biliniar { extrapolate: false }
Self { extrapolate: false, allow_default: false }
}

pub fn extrapolate(mut self, yes: bool) -> Self {
self.extrapolate = yes;
self
}

pub fn allow_default(mut self, value: bool) -> Self {
self.allow_default = value;
self
}
}

impl Default for Biliniar {
impl Default for Bilinear {
fn default() -> Self {
Self::new()
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum BuilderError {
pub enum InterpolateError {
#[error("{0}")]
OutOfBounds(String),
#[error("{0}")]
InvalidArguments(String),
}

/// cast `a` from type `A` to type `B` without any safety checks
Expand Down