use crate::StrError;
pub fn num_divisions(ndiv_min: usize, ndiv_long: usize, xmin: &[f64], xmax: &[f64]) -> Result<Vec<usize>, StrError> {
if ndiv_min < 1 {
return Err("ndiv_min must be ≥ 1");
}
if ndiv_long <= ndiv_min {
return Err("ndiv_long must be > ndiv_min");
}
if xmin.len() != xmax.len() {
return Err("xmin.len() must be equal to xmax.len()");
}
let ndim = xmin.len();
if ndim < 2 {
return Err("ndim must be ≥ 2");
}
let delta: Vec<_> = xmin.iter().zip(xmax).map(|(a, b)| *b - *a).collect();
let mut index_long = 0;
let mut delta_long = delta[index_long];
for i in 1..ndim {
if delta[i] > delta_long {
index_long = i;
delta_long = delta[i];
}
}
let mut ndiv = vec![0; ndim];
for i in 0..ndim {
if delta[i] <= 0.0 {
return Err("xmax must be greater than xmin");
}
if i == index_long {
ndiv[i] = ndiv_long;
} else {
ndiv[i] = ((delta[i] / delta_long) * (ndiv_long as f64)) as usize;
ndiv[i] = usize::max(ndiv_min, ndiv[i]);
}
}
Ok(ndiv)
}
#[cfg(test)]
mod tests {
use super::num_divisions;
#[test]
fn num_divisions_fails_on_errors() {
assert_eq!(
num_divisions(0, 20, &[0.0, 0.0], &[1.0, 1.0]).err(),
Some("ndiv_min must be ≥ 1")
);
assert_eq!(
num_divisions(2, 1, &[0.0, 0.0], &[1.0, 1.0]).err(),
Some("ndiv_long must be > ndiv_min")
);
assert_eq!(
num_divisions(2, 3, &[0.0, 0.0], &[1.0, 1.0, 1.0]).err(),
Some("xmin.len() must be equal to xmax.len()")
);
assert_eq!(num_divisions(2, 3, &[0.0], &[1.0]).err(), Some("ndim must be ≥ 2"));
assert_eq!(
num_divisions(2, 20, &[2.0, 2.0], &[0.0, 0.0]).err(),
Some("xmax must be greater than xmin")
);
}
#[test]
fn num_divisions_works() {
assert_eq!(num_divisions(1, 10, &[0.0, 0.0], &[1.0, 1.0]).unwrap(), &[10, 10]);
assert_eq!(num_divisions(2, 10, &[0.0, 0.0], &[1.0, 1.0]).unwrap(), &[10, 10]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[100.0, 100.0]).unwrap(), &[20, 20]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[1.0, 2.0]).unwrap(), &[10, 20]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[2.0, 1.0]).unwrap(), &[20, 10]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[1.0, 4.0]).unwrap(), &[5, 20]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[1.0, 5.0]).unwrap(), &[4, 20]);
assert_eq!(num_divisions(2, 20, &[0.0, 0.0], &[1.0, 10.0]).unwrap(), &[2, 20]);
assert_eq!(num_divisions(1, 20, &[0.0, 0.0], &[1.0, 100.0]).unwrap(), &[1, 20]);
assert_eq!(num_divisions(2, 20, &[0.0, 0.0], &[1.0, 100.0]).unwrap(), &[2, 20]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[10000.0, 1.0]).unwrap(), &[20, 3]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[10.0, 3.0]).unwrap(), &[20, 6]);
assert_eq!(num_divisions(3, 20, &[0.0, 0.0], &[10.0, 3.5]).unwrap(), &[20, 7]);
assert_eq!(num_divisions(3, 20, &[-1.0, -2.0], &[1.0, 2.0]).unwrap(), &[10, 20]);
}
}