use std::marker::PhantomData;
use crate::Accelerator;
use crate::Cache;
use crate::DomainError;
use crate::Interp2dType;
use crate::Interpolation2d;
use crate::InterpolationError;
use crate::types::utils::check_if_inbounds;
use crate::types::utils::check2d_data;
const MIN_SIZE: usize = 2;
#[doc(alias = "gsl_interp2d_bilinear")]
pub struct Bilinear;
impl<T> Interp2dType<T> for Bilinear
where
T: crate::Num,
{
type Interpolation2d = BilinearInterp<T>;
fn build(&self, xa: &[T], ya: &[T], za: &[T]) -> Result<BilinearInterp<T>, InterpolationError> {
check2d_data(xa, ya, za, MIN_SIZE)?;
Ok(BilinearInterp {
_variable_type: PhantomData,
})
}
fn name(&self) -> &str {
"Bilinear"
}
fn min_size(&self) -> usize {
MIN_SIZE
}
}
pub struct BilinearInterp<T> {
_variable_type: PhantomData<T>,
}
impl<T> Interpolation2d<T> for BilinearInterp<T>
where
T: crate::Num,
{
#[allow(unused_variables)]
fn eval_extrap(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
let is_uptodate = cache.is_uptodate(xa, ya, x, y);
if !is_uptodate {
cache.update_step1(xa, ya, za, x, y, xacc, yacc)?;
}
let (xlo, _xhi, ylo, _yhi) = cache.get_xy_grid_values();
let (zminmin, zminmax, zmaxmin, zmaxmax) = cache.get_z_grid_values();
let (dx, dy) = cache.get_partials();
debug_assert!(dx > T::zero());
debug_assert!(dy > T::zero());
let t = (x - xlo) / dx;
let u = (y - ylo) / dy;
let one = T::one();
let result = (one - t) * (one - u) * zminmin
+ t * (one - u) * zmaxmin
+ (one - t) * u * zminmax
+ t * u * zmaxmax;
Ok(result)
}
#[allow(unused_variables)]
fn eval_deriv_x(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
check_if_inbounds(xa, x)?;
check_if_inbounds(ya, y)?;
let is_uptodate = cache.is_uptodate(xa, ya, x, y);
if !is_uptodate {
cache.update_step1(xa, ya, za, x, y, xacc, yacc)?;
}
let (xlo, _xhi, ylo, _yhi) = cache.get_xy_grid_values();
let (zminmin, zminmax, zmaxmin, zmaxmax) = cache.get_z_grid_values();
let (dx, dy) = cache.get_partials();
debug_assert!(dx > T::zero());
debug_assert!(dy > T::zero());
let one = T::one();
let dt = one / dx;
let u = (y - ylo) / dy;
let result = dt * (-(one - u) * zminmin + (one - u) * zmaxmin - u * zminmax + u * zmaxmax);
Ok(result)
}
#[allow(unused_variables)]
fn eval_deriv_y(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
check_if_inbounds(xa, x)?;
check_if_inbounds(ya, y)?;
let is_uptodate = cache.is_uptodate(xa, ya, x, y);
if !is_uptodate {
cache.update_step1(xa, ya, za, x, y, xacc, yacc)?;
}
let (xlo, _xhi, ylo, _yhi) = cache.get_xy_grid_values();
let (zminmin, zminmax, zmaxmin, zmaxmax) = cache.get_z_grid_values();
let (dx, dy) = cache.get_partials();
debug_assert!(dx > T::zero());
debug_assert!(dy > T::zero());
let one = T::one();
let t = (x - xlo) / dx;
let du = one / dy;
let result = du * (-(one - t) * zminmin - t * zmaxmin + (one - t) * zminmax + t * zmaxmax);
Ok(result)
}
#[allow(unused_variables)]
fn eval_deriv_xx(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
check_if_inbounds(xa, x)?;
check_if_inbounds(ya, y)?;
Ok(T::zero())
}
#[allow(unused_variables)]
fn eval_deriv_yy(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
check_if_inbounds(xa, x)?;
check_if_inbounds(ya, y)?;
Ok(T::zero())
}
#[allow(unused_variables)]
fn eval_deriv_xy(
&self,
xa: &[T],
ya: &[T],
za: &[T],
x: T,
y: T,
xacc: &mut Accelerator,
yacc: &mut Accelerator,
cache: &mut Cache<T>,
) -> Result<T, DomainError> {
check_if_inbounds(xa, x)?;
check_if_inbounds(ya, y)?;
let is_uptodate = cache.is_uptodate(xa, ya, x, y);
if !is_uptodate {
cache.update_step1(xa, ya, za, x, y, xacc, yacc)?;
}
let (xlo, _xhi, ylo, _yhi) = cache.get_xy_grid_values();
let (zminmin, zminmax, zmaxmin, zmaxmax) = cache.get_z_grid_values();
let (dx, dy) = cache.get_partials();
let one = T::one();
let dt = one / dx;
let du = one / dy;
let result = dt * du * (zminmin - zmaxmin - zminmax + zmaxmax);
Ok(result)
}
}