use std::cmp::max;
pub fn abridge<const DIGITS: usize>(value: f64, abridge: Abridging, rounding: Rounding) -> f64 {
let power = 10.0f64.powi(trailing_digits::<DIGITS>(value, abridge) as _);
round(value * power, rounding) / power
}
fn round(value: f64, rounding: Rounding) -> f64 {
match rounding {
Rounding::Floor => value.floor(),
Rounding::Ceil => value.ceil(),
Rounding::Round => value.round(),
}
}
fn trailing_digits<const DIGITS: usize>(value: f64, abridge: Abridging) -> usize {
let leading_digits = value.abs().log10().ceil();
match abridge {
Abridging::Significant => max(0, DIGITS as isize - leading_digits as isize) as _,
Abridging::Mantissa => DIGITS,
Abridging::Total => DIGITS.saturating_sub(leading_digits as usize),
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Abridging {
Significant,
Mantissa,
Total,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Rounding {
Floor,
Ceil,
Round,
}
pub mod prelude {
pub use crate::{
abridge,
Abridging::{Mantissa, Significant, Total},
Rounding::{Ceil, Floor, Round},
};
}