1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
/// Represents the base for units [Prefix](crate::prefix::Prefix).
///
#[derive(Debug, PartialEq)]
pub enum Base {
/// The most common base, where 1 k means `1000,` 1 M means `1000^2`, ...
B1000,
/// A very common base for bibytes, where 1 kiB means `1024`, 1 MiB means
/// `1024 * 1024`, ...
B1024,
}
impl Base {
/// Using `floor()`, returns the closest integer exponent to represent the
/// provided value `x` in the self `Base`.
///
/// The returned integer exponent is a multiple of 3 in order to match the
/// prefixes' exponents.
///
/// # Example
///
/// ```
/// use si_scale::base::Base;
///
/// let x: f32 = 5.4e4;
/// let actual = Base::B1000.integral_exponent_for(x);
/// assert_eq!(actual, 3); // 1e3
///
/// let x: f64 = -5.4e-4;
/// let actual = Base::B1000.integral_exponent_for(x);
/// assert_eq!(actual, -6); // 1e-6
/// ```
///
pub fn integral_exponent_for<F>(&self, x: F) -> i32
where
F: Into<f64>,
{
let x: f64 = x.into();
match self {
Self::B1000 => (x.abs().log10() / 3f64).floor() as i32 * 3,
Self::B1024 => (x.abs().log2() / 10f64).floor() as i32 * 3,
}
}
/// This helper function returns a `f64` scaling factor for the mantissa,
/// obtained by raising self to the power of the provided `exponent`
/// divided by 3.
///
/// # Example
///
/// ```
/// use si_scale::base::Base;
///
/// assert_eq!(Base::B1000.pow(9), 1e9);
/// assert_eq!(Base::B1024.pow(3), 1024f64)
/// ```
///
pub fn pow(&self, exponent: i32) -> f64 {
match self {
Self::B1000 => 1000f64.powf(exponent as f64 / 3f64),
Self::B1024 => 1024f64.powf(exponent as f64 / 3f64),
}
}
}