Skip to content

Commit 9968ebe

Browse files
committed
Merge branch 'main' into cubic
2 parents 75473f0 + 1eeca7e commit 9968ebe

File tree

5 files changed

+147
-51
lines changed

5 files changed

+147
-51
lines changed

src/lib.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ pub use ndarray;
155155
pub(crate) use ndarray::prelude::*;
156156
pub(crate) use ndarray::{Data, Ix, RawDataClone};
157157

158-
pub(crate) use num_traits::{clamp, Num, One};
158+
pub(crate) use num_traits::{clamp, Euclid, Num, One};
159159

160160
pub(crate) use dyn_clone::*;
161161

@@ -218,6 +218,8 @@ pub enum Extrapolate<T> {
218218
Fill(T),
219219
/// Restrict interpolant point to the limits of the interpolation grid, using [`num_traits::clamp`].
220220
Clamp,
221+
/// Wrap around to other end of periodic data.
222+
Wrap,
221223
/// Return an error when interpolant point is beyond the limits of the interpolation grid.
222224
#[default]
223225
Error,
@@ -270,3 +272,32 @@ macro_rules! extrapolate_impl {
270272
};
271273
}
272274
pub(crate) use extrapolate_impl;
275+
276+
/// Wrap value around data bounds.
277+
/// Assumes `min` < `max`.
278+
pub(crate) fn wrap<T: Num + Euclid + Copy>(input: T, min: T, max: T) -> T {
279+
min + (input - min).rem_euclid(&(max - min))
280+
}
281+
282+
#[cfg(test)]
283+
mod tests {
284+
use crate::wrap;
285+
286+
#[test]
287+
fn test() {
288+
assert_eq!(wrap(-3, -2, 5), 4);
289+
assert_eq!(wrap(3, -2, 5), 3);
290+
assert_eq!(wrap(6, -2, 5), -1);
291+
assert_eq!(wrap(5, 0, 10), 5);
292+
assert_eq!(wrap(11, 0, 10), 1);
293+
assert_eq!(wrap(-3, 0, 10), 7);
294+
assert_eq!(wrap(-11, 0, 10), 9);
295+
assert_eq!(wrap(-0.1, -2., -1.), -1.1);
296+
assert_eq!(wrap(-0., -2., -1.), -2.0);
297+
assert_eq!(wrap(0.1, -2., -1.), -1.9);
298+
assert_eq!(wrap(-0.5, -1., 1.), -0.5);
299+
assert_eq!(wrap(0., -1., 1.), 0.);
300+
assert_eq!(wrap(0.5, -1., 1.), 0.5);
301+
assert_eq!(wrap(0.8, -1., 1.), 0.8);
302+
}
303+
}

src/n/mod.rs

+66-8
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ where
180180
impl<D, S> Interpolator<D::Elem> for InterpND<D, S>
181181
where
182182
D: Data + RawDataClone + Clone,
183-
D::Elem: PartialOrd + Debug + Clone,
183+
D::Elem: Num + Euclid + PartialOrd + Debug + Copy,
184184
S: StrategyND<D> + Clone,
185185
{
186186
fn ndim(&self) -> usize {
@@ -211,12 +211,25 @@ where
211211
.iter()
212212
.enumerate()
213213
.map(|(dim, pt)| {
214-
clamp(
214+
*clamp(
215215
pt,
216216
self.data.grid[dim].first().unwrap(),
217217
self.data.grid[dim].last().unwrap(),
218218
)
219-
.clone()
219+
})
220+
.collect();
221+
return self.strategy.interpolate(&self.data, &clamped_point);
222+
}
223+
Extrapolate::Wrap => {
224+
let clamped_point: Vec<_> = point
225+
.iter()
226+
.enumerate()
227+
.map(|(dim, pt)| {
228+
wrap(
229+
*pt,
230+
*self.data.grid[dim].first().unwrap(),
231+
*self.data.grid[dim].last().unwrap(),
232+
)
220233
})
221234
.collect();
222235
return self.strategy.interpolate(&self.data, &clamped_point);
@@ -514,7 +527,7 @@ mod tests {
514527
}
515528

516529
#[test]
517-
fn test_extrapolate_fill_value() {
530+
fn test_extrapolate_fill() {
518531
let interp = InterpND::new(
519532
vec![array![0.1, 1.1], array![0.2, 1.2], array![0.3, 1.3]],
520533
array![[[0., 1.], [2., 3.]], [[4., 5.], [6., 7.]],].into_dyn(),
@@ -534,15 +547,60 @@ mod tests {
534547

535548
#[test]
536549
fn test_extrapolate_clamp() {
550+
let x = array![0.1, 1.1];
551+
let y = array![0.2, 1.2];
552+
let z = array![0.3, 1.3];
553+
let values = array![[[0., 1.], [2., 3.]], [[4., 5.], [6., 7.]],].into_dyn();
537554
let interp = InterpND::new(
538-
vec![array![0.1, 1.1], array![0.2, 1.2], array![0.3, 1.3]],
539-
array![[[0., 1.], [2., 3.]], [[4., 5.], [6., 7.]],].into_dyn(),
555+
vec![x.view(), y.view(), z.view()],
556+
values.view(),
540557
Linear,
541558
Extrapolate::Clamp,
542559
)
543560
.unwrap();
544-
assert_eq!(interp.interpolate(&[-1., -1., -1.]).unwrap(), 0.);
545-
assert_eq!(interp.interpolate(&[2., 2., 2.]).unwrap(), 7.);
561+
assert_eq!(
562+
interp.interpolate(&[-1., -1., -1.]).unwrap(),
563+
values[[0, 0, 0]]
564+
);
565+
assert_eq!(
566+
interp.interpolate(&[-1., 2., -1.]).unwrap(),
567+
values[[0, 1, 0]]
568+
);
569+
assert_eq!(
570+
interp.interpolate(&[2., -1., 2.]).unwrap(),
571+
values[[1, 0, 1]]
572+
);
573+
assert_eq!(
574+
interp.interpolate(&[2., 2., 2.]).unwrap(),
575+
values[[1, 1, 1]]
576+
);
577+
}
578+
579+
#[test]
580+
fn test_extrapolate_wrap() {
581+
let interp = InterpND::new(
582+
vec![array![0., 1.], array![0., 1.], array![0., 1.]],
583+
array![[[0., 1.], [2., 3.]], [[4., 5.], [6., 7.]],].into_dyn(),
584+
Linear,
585+
Extrapolate::Wrap,
586+
)
587+
.unwrap();
588+
assert_eq!(
589+
interp.interpolate(&[-0.25, -0.2, -0.4]).unwrap(),
590+
interp.interpolate(&[0.75, 0.8, 0.6]).unwrap(),
591+
);
592+
assert_eq!(
593+
interp.interpolate(&[-0.25, 2.1, -0.4]).unwrap(),
594+
interp.interpolate(&[0.75, 0.1, 0.6]).unwrap(),
595+
);
596+
assert_eq!(
597+
interp.interpolate(&[-0.25, 2.1, 2.3]).unwrap(),
598+
interp.interpolate(&[0.75, 0.1, 0.3]).unwrap(),
599+
);
600+
assert_eq!(
601+
interp.interpolate(&[2.5, 2.1, 2.3]).unwrap(),
602+
interp.interpolate(&[0.5, 0.1, 0.3]).unwrap(),
603+
);
546604
}
547605

548606
#[test]

src/one/mod.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ where
115115
impl<D, S> Interpolator<D::Elem> for Interp1D<D, S>
116116
where
117117
D: Data + RawDataClone + Clone,
118-
D::Elem: PartialOrd + Debug + Clone,
118+
D::Elem: Num + Euclid + PartialOrd + Debug + Copy,
119119
S: Strategy1D<D> + Clone,
120120
{
121121
/// Returns `1`.
@@ -140,13 +140,20 @@ where
140140
Extrapolate::Enable => {}
141141
Extrapolate::Fill(value) => return Ok(value.clone()),
142142
Extrapolate::Clamp => {
143-
let clamped_point = &[clamp(
143+
let clamped_point = [*clamp(
144144
&point[0],
145145
self.data.grid[0].first().unwrap(),
146146
self.data.grid[0].last().unwrap(),
147-
)
148-
.clone()];
149-
return self.strategy.interpolate(&self.data, clamped_point);
147+
)];
148+
return self.strategy.interpolate(&self.data, &clamped_point);
149+
}
150+
Extrapolate::Wrap => {
151+
let wrapped_point = [wrap(
152+
point[0],
153+
*self.data.grid[0].first().unwrap(),
154+
*self.data.grid[0].last().unwrap(),
155+
)];
156+
return self.strategy.interpolate(&self.data, &wrapped_point);
150157
}
151158
Extrapolate::Error => {
152159
return Err(InterpolateError::ExtrapolateError(format!(
@@ -285,7 +292,7 @@ mod tests {
285292
}
286293

287294
#[test]
288-
fn test_extrapolate_fill_value() {
295+
fn test_extrapolate_fill() {
289296
let interp = Interp1D::new(
290297
array![0., 1., 2., 3., 4.],
291298
array![0.2, 0.4, 0.6, 0.8, 1.0],

src/three/mod.rs

+18-21
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ where
134134
impl<D, S> Interpolator<D::Elem> for Interp3D<D, S>
135135
where
136136
D: Data + RawDataClone + Clone,
137-
D::Elem: PartialOrd + Debug + Clone,
137+
D::Elem: Num + Euclid + PartialOrd + Debug + Copy,
138138
S: Strategy3D<D> + Clone,
139139
{
140140
/// Returns `3`.
@@ -161,27 +161,24 @@ where
161161
Extrapolate::Enable => {}
162162
Extrapolate::Fill(value) => return Ok(value.clone()),
163163
Extrapolate::Clamp => {
164-
let clamped_point = &[
165-
clamp(
166-
&point[0],
167-
self.data.grid[0].first().unwrap(),
168-
self.data.grid[0].last().unwrap(),
164+
let clamped_point = core::array::from_fn(|i| {
165+
*clamp(
166+
&point[i],
167+
self.data.grid[i].first().unwrap(),
168+
self.data.grid[i].last().unwrap(),
169169
)
170-
.clone(),
171-
clamp(
172-
&point[1],
173-
self.data.grid[1].first().unwrap(),
174-
self.data.grid[1].last().unwrap(),
175-
)
176-
.clone(),
177-
clamp(
178-
&point[2],
179-
self.data.grid[2].first().unwrap(),
180-
self.data.grid[2].last().unwrap(),
170+
});
171+
return self.strategy.interpolate(&self.data, &clamped_point);
172+
}
173+
Extrapolate::Wrap => {
174+
let wrapped_point = core::array::from_fn(|i| {
175+
wrap(
176+
point[i],
177+
*self.data.grid[i].first().unwrap(),
178+
*self.data.grid[i].last().unwrap(),
181179
)
182-
.clone(),
183-
];
184-
return self.strategy.interpolate(&self.data, clamped_point);
180+
});
181+
return self.strategy.interpolate(&self.data, &wrapped_point);
185182
}
186183
Extrapolate::Error => {
187184
errors.push(format!(
@@ -379,7 +376,7 @@ mod tests {
379376
}
380377

381378
#[test]
382-
fn test_extrapolate_fill_value() {
379+
fn test_extrapolate_fill() {
383380
let interp = Interp3D::new(
384381
array![0.1, 1.1],
385382
array![0.2, 1.2],

src/two/mod.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ where
120120
impl<D, S> Interpolator<D::Elem> for Interp2D<D, S>
121121
where
122122
D: Data + RawDataClone + Clone,
123-
D::Elem: PartialOrd + Debug + Clone,
123+
D::Elem: Num + Euclid + PartialOrd + Debug + Copy,
124124
S: Strategy2D<D> + Clone,
125125
{
126126
/// Returns `2`.
@@ -147,21 +147,24 @@ where
147147
Extrapolate::Enable => {}
148148
Extrapolate::Fill(value) => return Ok(value.clone()),
149149
Extrapolate::Clamp => {
150-
let clamped_point = &[
151-
clamp(
152-
&point[0],
153-
self.data.grid[0].first().unwrap(),
154-
self.data.grid[0].last().unwrap(),
150+
let clamped_point = core::array::from_fn(|i| {
151+
*clamp(
152+
&point[i],
153+
self.data.grid[i].first().unwrap(),
154+
self.data.grid[i].last().unwrap(),
155155
)
156-
.clone(),
157-
clamp(
158-
&point[1],
159-
self.data.grid[1].first().unwrap(),
160-
self.data.grid[1].last().unwrap(),
156+
});
157+
return self.strategy.interpolate(&self.data, &clamped_point);
158+
}
159+
Extrapolate::Wrap => {
160+
let wrapped_point = core::array::from_fn(|i| {
161+
wrap(
162+
point[i],
163+
*self.data.grid[i].first().unwrap(),
164+
*self.data.grid[i].last().unwrap(),
161165
)
162-
.clone(),
163-
];
164-
return self.strategy.interpolate(&self.data, clamped_point);
166+
});
167+
return self.strategy.interpolate(&self.data, &wrapped_point);
165168
}
166169
Extrapolate::Error => {
167170
errors.push(format!(
@@ -310,7 +313,7 @@ mod tests {
310313
}
311314

312315
#[test]
313-
fn test_extrapolate_fill_value() {
316+
fn test_extrapolate_fill() {
314317
let interp = Interp2D::new(
315318
array![0.1, 1.1],
316319
array![0.2, 1.2],

0 commit comments

Comments
 (0)