Skip to content

Commit 447969f

Browse files
committed
clean up namespace
1 parent 14de2f0 commit 447969f

File tree

5 files changed

+134
-131
lines changed

5 files changed

+134
-131
lines changed

src/interpolator/mod.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,100 @@ pub use one::{Interp1D, Interp1DOwned, Interp1DViewed};
1313
pub use three::{Interp3D, Interp3DOwned, Interp3DViewed};
1414
pub use two::{Interp2D, Interp2DOwned, Interp2DViewed};
1515
pub use zero::Interp0D;
16+
17+
/// An interpolator of data type `T`
18+
///
19+
/// This trait is dyn-compatible, meaning you can use:
20+
/// `Box<dyn Interpolator<_>>`
21+
/// and swap the contained interpolator at runtime.
22+
pub trait Interpolator<T>: DynClone {
23+
/// Interpolator dimensionality.
24+
fn ndim(&self) -> usize;
25+
/// Validate interpolator data.
26+
fn validate(&mut self) -> Result<(), ValidateError>;
27+
/// Interpolate at supplied point.
28+
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError>;
29+
}
30+
31+
clone_trait_object!(<T> Interpolator<T>);
32+
33+
impl<T> Interpolator<T> for Box<dyn Interpolator<T>> {
34+
fn ndim(&self) -> usize {
35+
(**self).ndim()
36+
}
37+
fn validate(&mut self) -> Result<(), ValidateError> {
38+
(**self).validate()
39+
}
40+
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError> {
41+
(**self).interpolate(point)
42+
}
43+
}
44+
45+
/// Extrapolation strategy
46+
///
47+
/// Controls what happens if supplied interpolant point
48+
/// is outside the bounds of the interpolation grid.
49+
#[derive(Clone, Copy, Debug, PartialEq, Default)]
50+
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
51+
pub enum Extrapolate<T> {
52+
/// Evaluate beyond the limits of the interpolation grid.
53+
Enable,
54+
/// If point is beyond grid limits, return this value instead.
55+
Fill(T),
56+
/// Restrict interpolant point to the limits of the interpolation grid, using [`num_traits::clamp`].
57+
Clamp,
58+
/// Wrap around to other end of periodic data.
59+
/// Does NOT check that first and last values are equal.
60+
Wrap,
61+
/// Return an error when interpolant point is beyond the limits of the interpolation grid.
62+
#[default]
63+
Error,
64+
}
65+
66+
macro_rules! extrapolate_impl {
67+
($InterpType:ident, $Strategy:ident) => {
68+
impl<D, S> $InterpType<D, S>
69+
where
70+
D: Data + RawDataClone + Clone,
71+
D::Elem: PartialEq + Debug,
72+
S: $Strategy<D> + Clone,
73+
{
74+
/// Set [`Extrapolate`] variant, checking validity.
75+
pub fn set_extrapolate(
76+
&mut self,
77+
extrapolate: Extrapolate<D::Elem>,
78+
) -> Result<(), ValidateError> {
79+
self.check_extrapolate(&extrapolate)?;
80+
self.extrapolate = extrapolate;
81+
Ok(())
82+
}
83+
84+
pub fn check_extrapolate(
85+
&self,
86+
extrapolate: &Extrapolate<D::Elem>,
87+
) -> Result<(), ValidateError> {
88+
// Check applicability of strategy and extrapolate setting
89+
if matches!(extrapolate, Extrapolate::Enable) && !self.strategy.allow_extrapolate()
90+
{
91+
return Err(ValidateError::ExtrapolateSelection(format!(
92+
"{:?}",
93+
self.extrapolate
94+
)));
95+
}
96+
// If using Extrapolate::Enable,
97+
// check that each grid dimension has at least two elements
98+
if matches!(self.extrapolate, Extrapolate::Enable) {
99+
for (i, g) in self.data.grid.iter().enumerate() {
100+
if g.len() < 2 {
101+
return Err(ValidateError::Other(format!(
102+
"at least 2 data points are required for extrapolation: dim {i}",
103+
)));
104+
}
105+
}
106+
}
107+
Ok(())
108+
}
109+
}
110+
};
111+
}
112+
pub(crate) use extrapolate_impl;

src/interpolator/n/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ where
226226
return self.strategy.interpolate(&self.data, &clamped_point);
227227
}
228228
Extrapolate::Wrap => {
229-
let clamped_point: Vec<_> = point
229+
let wrapped_point: Vec<_> = point
230230
.iter()
231231
.enumerate()
232232
.map(|(dim, pt)| {
@@ -237,7 +237,7 @@ where
237237
)
238238
})
239239
.collect();
240-
return self.strategy.interpolate(&self.data, &clamped_point);
240+
return self.strategy.interpolate(&self.data, &wrapped_point);
241241
}
242242
Extrapolate::Error => {
243243
errors.push(format!(

src/lib.rs

Lines changed: 5 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@
125125
/// - [`strategy::RightNearest`]
126126
/// - The extrapolation setting enum: [`Extrapolate`]
127127
pub mod prelude {
128-
pub use crate::interpolator::{Interp0D, Interp1D, Interp2D, Interp3D, InterpND};
128+
pub use crate::interpolator::{
129+
Extrapolate, Interp0D, Interp1D, Interp2D, Interp3D, InterpND, Interpolator,
130+
};
129131
pub use crate::strategy;
130-
pub use crate::Extrapolate;
131-
pub use crate::Interpolator;
132132
}
133133

134134
pub mod error;
@@ -137,6 +137,7 @@ pub mod strategy;
137137
pub mod interpolator;
138138
pub use interpolator::data;
139139
pub(crate) use interpolator::data::*;
140+
pub(crate) use interpolator::*;
140141

141142
pub(crate) use error::*;
142143
pub(crate) use strategy::traits::*;
@@ -169,103 +170,6 @@ macro_rules! assert_approx_eq {
169170
#[cfg(test)]
170171
pub(crate) use assert_approx_eq;
171172

172-
/// An interpolator of data type `T`
173-
///
174-
/// This trait is dyn-compatible, meaning you can use:
175-
/// `Box<dyn Interpolator<_>>`
176-
/// and swap the contained interpolator at runtime.
177-
pub trait Interpolator<T>: DynClone {
178-
/// Interpolator dimensionality.
179-
fn ndim(&self) -> usize;
180-
/// Validate interpolator data.
181-
fn validate(&mut self) -> Result<(), ValidateError>;
182-
/// Interpolate at supplied point.
183-
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError>;
184-
}
185-
186-
clone_trait_object!(<T> Interpolator<T>);
187-
188-
impl<T> Interpolator<T> for Box<dyn Interpolator<T>> {
189-
fn ndim(&self) -> usize {
190-
(**self).ndim()
191-
}
192-
fn validate(&mut self) -> Result<(), ValidateError> {
193-
(**self).validate()
194-
}
195-
fn interpolate(&self, point: &[T]) -> Result<T, InterpolateError> {
196-
(**self).interpolate(point)
197-
}
198-
}
199-
200-
/// Extrapolation strategy
201-
///
202-
/// Controls what happens if supplied interpolant point
203-
/// is outside the bounds of the interpolation grid.
204-
#[derive(Clone, Copy, Debug, PartialEq, Default)]
205-
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
206-
pub enum Extrapolate<T> {
207-
/// Evaluate beyond the limits of the interpolation grid.
208-
Enable,
209-
/// If point is beyond grid limits, return this value instead.
210-
Fill(T),
211-
/// Restrict interpolant point to the limits of the interpolation grid, using [`num_traits::clamp`].
212-
Clamp,
213-
/// Wrap around to other end of periodic data.
214-
/// Does NOT check that first and last values are equal.
215-
Wrap,
216-
/// Return an error when interpolant point is beyond the limits of the interpolation grid.
217-
#[default]
218-
Error,
219-
}
220-
221-
macro_rules! extrapolate_impl {
222-
($InterpType:ident, $Strategy:ident) => {
223-
impl<D, S> $InterpType<D, S>
224-
where
225-
D: Data + RawDataClone + Clone,
226-
D::Elem: PartialEq + Debug,
227-
S: $Strategy<D> + Clone,
228-
{
229-
/// Set [`Extrapolate`] variant, checking validity.
230-
pub fn set_extrapolate(
231-
&mut self,
232-
extrapolate: Extrapolate<D::Elem>,
233-
) -> Result<(), ValidateError> {
234-
self.check_extrapolate(&extrapolate)?;
235-
self.extrapolate = extrapolate;
236-
Ok(())
237-
}
238-
239-
pub fn check_extrapolate(
240-
&self,
241-
extrapolate: &Extrapolate<D::Elem>,
242-
) -> Result<(), ValidateError> {
243-
// Check applicability of strategy and extrapolate setting
244-
if matches!(extrapolate, Extrapolate::Enable) && !self.strategy.allow_extrapolate()
245-
{
246-
return Err(ValidateError::ExtrapolateSelection(format!(
247-
"{:?}",
248-
self.extrapolate
249-
)));
250-
}
251-
// If using Extrapolate::Enable,
252-
// check that each grid dimension has at least two elements
253-
if matches!(self.extrapolate, Extrapolate::Enable) {
254-
for (i, g) in self.data.grid.iter().enumerate() {
255-
if g.len() < 2 {
256-
return Err(ValidateError::Other(format!(
257-
"at least 2 data points are required for extrapolation: dim {i}",
258-
)));
259-
}
260-
}
261-
}
262-
Ok(())
263-
}
264-
}
265-
};
266-
}
267-
pub(crate) use extrapolate_impl;
268-
269173
/// Wrap value around data bounds.
270174
/// Assumes `min` < `max`.
271175
pub(crate) fn wrap<T: Num + Euclid + Copy>(input: T, min: T, max: T) -> T {
@@ -274,7 +178,7 @@ pub(crate) fn wrap<T: Num + Euclid + Copy>(input: T, min: T, max: T) -> T {
274178

275179
#[cfg(test)]
276180
mod tests {
277-
use crate::wrap;
181+
use super::wrap;
278182

279183
#[test]
280184
fn test() {

src/strategy/mod.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,6 @@ use super::*;
44

55
pub mod traits;
66

7-
// This method contains code from RouteE Compass, another open-source NREL-developed tool
8-
// <https://www.nrel.gov/transportation/route-energy-prediction-model.html>
9-
// <https://github.com/NREL/routee-compass/>
10-
pub fn find_nearest_index<T: PartialOrd>(arr: ArrayView1<T>, target: &T) -> usize {
11-
if target == arr.last().unwrap() {
12-
return arr.len() - 2;
13-
}
14-
15-
let mut low = 0;
16-
let mut high = arr.len() - 1;
17-
18-
while low < high {
19-
let mid = low + (high - low) / 2;
20-
21-
if &arr[mid] >= target {
22-
high = mid;
23-
} else {
24-
low = mid + 1;
25-
}
26-
}
27-
28-
if low > 0 && &arr[low] >= target {
29-
low - 1
30-
} else {
31-
low
32-
}
33-
}
34-
357
/// Linear interpolation: <https://en.wikipedia.org/wiki/Linear_interpolation>
368
#[derive(Debug, Clone, PartialEq)]
379
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]

src/strategy/traits.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
use super::*;
22

3+
/// Find nearest index in `arr` left of `target`
4+
///
5+
/// This method contains code from RouteE Compass, another open-source NREL-developed tool
6+
/// <https://www.nrel.gov/transportation/route-energy-prediction-model.html>
7+
/// <https://github.com/NREL/routee-compass/>
8+
pub fn find_nearest_index<T: PartialOrd>(arr: ArrayView1<T>, target: &T) -> usize {
9+
if target == arr.last().unwrap() {
10+
return arr.len() - 2;
11+
}
12+
13+
let mut low = 0;
14+
let mut high = arr.len() - 1;
15+
16+
while low < high {
17+
let mid = low + (high - low) / 2;
18+
19+
if &arr[mid] >= target {
20+
high = mid;
21+
} else {
22+
low = mid + 1;
23+
}
24+
}
25+
26+
if low > 0 && &arr[low] >= target {
27+
low - 1
28+
} else {
29+
low
30+
}
31+
}
32+
333
pub trait Strategy1D<D>: Debug + DynClone
434
where
535
D: Data + RawDataClone + Clone,

0 commit comments

Comments
 (0)