use std::collections::BTreeMap;
use crate::types::{BaseUnit, Dimensionality, Number, Numeric};
pub(crate) fn fast_decompose(
value: &Number,
derived_units: &BTreeMap<Dimensionality, String>,
) -> Dimensionality {
let mut best = None;
'outer: for (unit, name) in derived_units.iter() {
for (dim, pow) in unit.iter() {
let vpow = value.unit.get(dim).cloned().unwrap_or(0);
let snum = (vpow - pow).signum();
if snum != 0 && snum != vpow.signum() {
continue 'outer;
}
}
let num = Number {
value: Numeric::one(),
unit: unit.clone(),
};
for &i in [-1, 1, 2].iter() {
let res = (value / &num.powi(i)).unwrap();
let score = res.complexity_score();
let better = best
.as_ref()
.map(|&(_, _, _, current)| score < current)
.unwrap_or(true);
if better {
best = Some((name, unit, i, score));
}
}
}
if let Some((name, unit, pow, score)) = best {
if score < value.complexity_score() {
let num = Number {
value: Numeric::one(),
unit: unit.clone(),
};
let mut res = (value / &num.powi(pow)).unwrap().unit;
res.insert(BaseUnit::new(&**name), pow as i64);
return res;
}
}
value.unit.clone()
}