use ndarray::{ArrayBase, AsArray, Dimension, ViewRepr, Zip};
use crate::prelude::*;
#[inline]
pub fn max<'a, T, A, D>(data: A, threads: Option<usize>) -> Result<T, ImgalError>
where
A: AsArray<'a, T, D>,
D: Dimension,
T: 'a + PartialOrd + Clone + Sync + Send,
{
let data: ArrayBase<ViewRepr<&'a T>, D> = data.into();
let av = data
.first()
.ok_or(ImgalError::InvalidParameterEmptyArray { param_name: "data" })?;
let max_cmp = |acc, v| if v > acc { v } else { acc };
Ok(par!(threads,
seq_exp: Zip::from(&data).fold(av, &max_cmp),
par_exp: Zip::from(&data).par_fold(|| av, &max_cmp, &max_cmp))
.clone())
}
#[inline]
pub fn min<'a, T, A, D>(data: A, threads: Option<usize>) -> Result<T, ImgalError>
where
A: AsArray<'a, T, D>,
D: Dimension,
T: 'a + PartialOrd + Clone + Sync,
{
let data: ArrayBase<ViewRepr<&'a T>, D> = data.into();
let av = data
.first()
.ok_or(ImgalError::InvalidParameterEmptyArray { param_name: "data" })?;
let min_cmp = |acc, v| if v < acc { v } else { acc };
Ok(par!(threads,
seq_exp: Zip::from(&data).fold(av, &min_cmp),
par_exp: Zip::from(&data).par_fold(|| av, &min_cmp, &min_cmp))
.clone())
}
#[inline]
pub fn min_max<'a, T, A, D>(data: A, threads: Option<usize>) -> Result<(T, T), ImgalError>
where
A: AsArray<'a, T, D>,
D: Dimension,
T: 'a + PartialOrd + Clone + Send + Sync,
{
let data: ArrayBase<ViewRepr<&'a T>, D> = data.into();
let av = data
.first()
.ok_or(ImgalError::InvalidParameterEmptyArray { param_name: "data" })?;
let mm_seq = || {
let mm = Zip::from(&data).fold((av, av), |acc, v| {
(
if v < acc.0 { v } else { acc.0 },
if v > acc.1 { v } else { acc.1 },
)
});
(mm.0.clone(), mm.1.clone())
};
let mm_par = || {
let mm = Zip::from(&data).par_fold(
|| (av, av),
|acc, v| {
(
if v < acc.0 { v } else { acc.0 },
if v > acc.1 { v } else { acc.1 },
)
},
|acc, v| {
(
if v.0 < acc.0 { v.0 } else { acc.0 },
if v.1 > acc.1 { v.1 } else { acc.1 },
)
},
);
(mm.0.clone(), mm.1.clone())
};
Ok(par!(threads, seq_exp: mm_seq(), par_exp: mm_par()))
}