qualia_core_db/solvers/units/
dimension.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub struct Dimension {
11 pub exponents: [i8; 7],
12}
13
14pub const LENGTH: usize = 0;
16pub const MASS: usize = 1;
17pub const TIME: usize = 2;
18pub const CURRENT: usize = 3;
19pub const TEMPERATURE: usize = 4;
20pub const AMOUNT: usize = 5;
21pub const LUMINOSITY: usize = 6;
22
23impl Dimension {
24 pub const fn new(exponents: [i8; 7]) -> Self {
25 Self { exponents }
26 }
27
28 const fn base(index: usize) -> Self {
30 let mut e = [0i8; 7];
31 e[index] = 1;
32 Self { exponents: e }
33 }
34
35 pub const DIMENSIONLESS: Dimension = Dimension::new([0; 7]);
36 pub const LENGTH: Dimension = Dimension::base(LENGTH);
37 pub const MASS: Dimension = Dimension::base(MASS);
38 pub const TIME: Dimension = Dimension::base(TIME);
39 pub const CURRENT: Dimension = Dimension::base(CURRENT);
40 pub const TEMPERATURE: Dimension = Dimension::base(TEMPERATURE);
41 pub const AMOUNT: Dimension = Dimension::base(AMOUNT);
42 pub const LUMINOSITY: Dimension = Dimension::base(LUMINOSITY);
43
44 pub const AREA: Dimension = Dimension::new([2, 0, 0, 0, 0, 0, 0]);
46 pub const VOLUME: Dimension = Dimension::new([3, 0, 0, 0, 0, 0, 0]);
47 pub const VELOCITY: Dimension = Dimension::new([1, 0, -1, 0, 0, 0, 0]);
49 pub const ACCELERATION: Dimension = Dimension::new([1, 0, -2, 0, 0, 0, 0]);
50 pub const FORCE: Dimension = Dimension::new([1, 1, -2, 0, 0, 0, 0]);
52 pub const ENERGY: Dimension = Dimension::new([2, 1, -2, 0, 0, 0, 0]);
54 pub const POWER: Dimension = Dimension::new([2, 1, -3, 0, 0, 0, 0]);
55 pub const PRESSURE: Dimension = Dimension::new([-1, 1, -2, 0, 0, 0, 0]);
57 pub const CHARGE: Dimension = Dimension::new([0, 0, 1, 1, 0, 0, 0]);
59 pub const FREQUENCY: Dimension = Dimension::new([0, 0, -1, 0, 0, 0, 0]);
61
62 pub fn is_dimensionless(&self) -> bool {
63 self.exponents == [0; 7]
64 }
65
66 pub fn mul(&self, other: &Dimension) -> Dimension {
68 let mut e = [0i8; 7];
69 for i in 0..7 {
70 e[i] = self.exponents[i].saturating_add(other.exponents[i]);
71 }
72 Dimension { exponents: e }
73 }
74
75 pub fn div(&self, other: &Dimension) -> Dimension {
77 let mut e = [0i8; 7];
78 for i in 0..7 {
79 e[i] = self.exponents[i].saturating_sub(other.exponents[i]);
80 }
81 Dimension { exponents: e }
82 }
83
84 pub fn powi(&self, n: i32) -> Dimension {
86 let mut e = [0i8; 7];
87 for i in 0..7 {
88 e[i] = (self.exponents[i] as i32 * n).clamp(i8::MIN as i32, i8::MAX as i32) as i8;
89 }
90 Dimension { exponents: e }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn products_and_quotients_compose() {
100 assert_eq!(Dimension::LENGTH.div(&Dimension::TIME), Dimension::VELOCITY);
102 assert_eq!(Dimension::FORCE.mul(&Dimension::LENGTH), Dimension::ENERGY);
104 assert_eq!(Dimension::ENERGY.div(&Dimension::TIME), Dimension::POWER);
106 assert_eq!(Dimension::FORCE.div(&Dimension::AREA), Dimension::PRESSURE);
108 }
109
110 #[test]
111 fn powers_scale_exponents() {
112 assert_eq!(Dimension::LENGTH.powi(2), Dimension::AREA);
113 assert_eq!(Dimension::LENGTH.powi(3), Dimension::VOLUME);
114 assert_eq!(
116 Dimension::VELOCITY.powi(2),
117 Dimension::new([2, 0, -2, 0, 0, 0, 0])
118 );
119 }
120
121 #[test]
122 fn dimensionless_detection() {
123 assert!(Dimension::DIMENSIONLESS.is_dimensionless());
124 assert!(Dimension::VELOCITY
126 .div(&Dimension::VELOCITY)
127 .is_dimensionless());
128 assert!(!Dimension::FORCE.is_dimensionless());
129 }
130}