Skip to content

Commit 0070d88

Browse files
committed
Combine MinMaxExt with PercentileExt
1 parent b94ccd9 commit 0070d88

File tree

3 files changed

+130
-144
lines changed

3 files changed

+130
-144
lines changed

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ extern crate rand;
99
extern crate quickcheck;
1010

1111
pub use maybe_nan::{MaybeNan, MaybeNanExt};
12-
pub use min_max::MinMaxExt;
1312
pub use percentile::{interpolate, PercentileExt};
1413
pub use sort::Sort1dExt;
1514

1615
mod maybe_nan;
17-
mod min_max;
1816
mod percentile;
1917
mod sort;

src/min_max.rs

Lines changed: 0 additions & 141 deletions
This file was deleted.

src/percentile.rs

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use interpolate::Interpolate;
22
use ndarray::prelude::*;
33
use ndarray::{Data, DataMut, RemoveAxis};
4-
use {MaybeNan, Sort1dExt};
4+
use std::cmp;
5+
use {MaybeNan, MaybeNanExt, Sort1dExt};
56

67
/// Interpolation strategies.
78
pub mod interpolate {
@@ -173,6 +174,62 @@ where
173174
S: Data<Elem = A>,
174175
D: Dimension,
175176
{
177+
/// Finds the elementwise minimum of the array.
178+
///
179+
/// **Panics** if the array is empty.
180+
fn min(&self) -> &A
181+
where
182+
A: Ord;
183+
184+
/// Finds the elementwise minimum of the array.
185+
///
186+
/// Returns `None` if any of the pairwise orderings tested by the function
187+
/// are undefined. (For example, this occurs if there are any
188+
/// floating-point NaN values in the array.)
189+
///
190+
/// Additionally, returns `None` if the array is empty.
191+
fn min_partialord(&self) -> Option<&A>
192+
where
193+
A: PartialOrd;
194+
195+
/// Finds the elementwise minimum of the array, skipping NaN values.
196+
///
197+
/// **Warning** This method will return a NaN value if none of the values
198+
/// in the array are non-NaN values. Note that the NaN value might not be
199+
/// in the array.
200+
fn min_skipnan(&self) -> &A
201+
where
202+
A: MaybeNan,
203+
A::NotNan: Ord;
204+
205+
/// Finds the elementwise maximum of the array.
206+
///
207+
/// **Panics** if the array is empty.
208+
fn max(&self) -> &A
209+
where
210+
A: Ord;
211+
212+
/// Finds the elementwise maximum of the array.
213+
///
214+
/// Returns `None` if any of the pairwise orderings tested by the function
215+
/// are undefined. (For example, this occurs if there are any
216+
/// floating-point NaN values in the array.)
217+
///
218+
/// Additionally, returns `None` if the array is empty.
219+
fn max_partialord(&self) -> Option<&A>
220+
where
221+
A: PartialOrd;
222+
223+
/// Finds the elementwise maximum of the array, skipping NaN values.
224+
///
225+
/// **Warning** This method will return a NaN value if none of the values
226+
/// in the array are non-NaN values. Note that the NaN value might not be
227+
/// in the array.
228+
fn max_skipnan(&self) -> &A
229+
where
230+
A: MaybeNan,
231+
A::NotNan: Ord;
232+
176233
/// Return the qth percentile of the data along the specified axis.
177234
///
178235
/// `q` needs to be a float between 0 and 1, bounds included.
@@ -227,6 +284,78 @@ where
227284
S: Data<Elem = A>,
228285
D: Dimension,
229286
{
287+
fn min(&self) -> &A
288+
where
289+
A: Ord,
290+
{
291+
let first = self
292+
.iter()
293+
.next()
294+
.expect("Attempted to find min of empty array.");
295+
self.fold(first, |acc, elem| if elem < acc { elem } else { acc })
296+
}
297+
298+
fn min_partialord(&self) -> Option<&A>
299+
where
300+
A: PartialOrd,
301+
{
302+
let first = self.iter().next()?;
303+
self.fold(Some(first), |acc, elem| match elem.partial_cmp(acc?)? {
304+
cmp::Ordering::Less => Some(elem),
305+
_ => acc,
306+
})
307+
}
308+
309+
fn min_skipnan(&self) -> &A
310+
where
311+
A: MaybeNan,
312+
A::NotNan: Ord,
313+
{
314+
let first = self.iter().next().and_then(|v| v.try_as_not_nan());
315+
A::from_not_nan_ref_opt(self.fold_skipnan(first, |acc, elem| {
316+
Some(match acc {
317+
Some(acc) => acc.min(elem),
318+
None => elem,
319+
})
320+
}))
321+
}
322+
323+
fn max(&self) -> &A
324+
where
325+
A: Ord,
326+
{
327+
let first = self
328+
.iter()
329+
.next()
330+
.expect("Attempted to find max of empty array.");
331+
self.fold(first, |acc, elem| if elem > acc { elem } else { acc })
332+
}
333+
334+
fn max_partialord(&self) -> Option<&A>
335+
where
336+
A: PartialOrd,
337+
{
338+
let first = self.iter().next()?;
339+
self.fold(Some(first), |acc, elem| match elem.partial_cmp(acc?)? {
340+
cmp::Ordering::Greater => Some(elem),
341+
_ => acc,
342+
})
343+
}
344+
345+
fn max_skipnan(&self) -> &A
346+
where
347+
A: MaybeNan,
348+
A::NotNan: Ord,
349+
{
350+
let first = self.iter().next().and_then(|v| v.try_as_not_nan());
351+
A::from_not_nan_ref_opt(self.fold_skipnan(first, |acc, elem| {
352+
Some(match acc {
353+
Some(acc) => acc.max(elem),
354+
None => elem,
355+
})
356+
}))
357+
}
358+
230359
fn percentile_axis_mut<I>(&mut self, axis: Axis, q: f64) -> Array<A, D::Smaller>
231360
where
232361
D: RemoveAxis,

0 commit comments

Comments
 (0)