whippyunits_core/
scale_exponents.rs

1/// Prime factorization into powers of 2, 3, 5, and pi.
2#[derive(Debug, Clone, Copy, PartialEq)]
3pub struct ScaleExponents(pub [i16; 4]);
4
5impl ScaleExponents {
6    /// `1`.
7    pub const IDENTITY: Self = Self([0; 4]);
8
9    /// A power of 2.
10    pub const fn _2(power: i16) -> Self {
11        Self([power, 0, 0, 0])
12    }
13
14    /// A power of 3.
15    pub const fn _3(power: i16) -> Self {
16        Self([0, power, 0, 0])
17    }
18
19    /// A power of 5.
20    pub const fn _5(power: i16) -> Self {
21        Self([0, 0, power, 0])
22    }
23
24    /// A power of pi.
25    #[allow(non_snake_case)]
26    pub const fn _Pi(power: i16) -> Self {
27        Self([0, 0, 0, power])
28    }
29
30    /// A power of 6.
31    pub const fn _6(power: i16) -> Self {
32        // We factorize 6 as 2 * 3 so we split the power cross those.
33        Self([power, power, 0, 0])
34    }
35
36    /// A power of 10.
37    pub const fn _10(power: i16) -> Self {
38        // We factorize 10 as 2 * 5 so we split the power cross those.
39        Self([power, 0, power, 0])
40    }
41
42    pub const fn mul(&self, rhs: Self) -> Self {
43        Self([
44            self.0[0] + rhs.0[0],
45            self.0[1] + rhs.0[1],
46            self.0[2] + rhs.0[2],
47            self.0[3] + rhs.0[3],
48        ])
49    }
50
51    pub const fn log10(&self) -> Option<i16> {
52        if let [x, 0, y, 0] = self.0
53            && x == y
54        {
55            Some(x)
56        } else {
57            None
58        }
59    }
60
61    pub const fn scalar_exp(&self, rhs: i16) -> Self {
62        Self([
63            self.0[0] * rhs,
64            self.0[1] * rhs,
65            self.0[2] * rhs,
66            self.0[3] * rhs,
67        ])
68    }
69
70    pub const fn neg(&self) -> Self {
71        Self([-self.0[0], -self.0[1], -self.0[2], -self.0[3]])
72    }
73}