microcad_lang/value/quantity/
mod.rs1pub mod error;
7pub mod ops;
8
9use crate::ty::*;
10use microcad_core::*;
11
12pub use error::*;
13
14const OUTPUT_PRECISION: i32 = 14;
15
16#[derive(Clone, Debug)]
18pub struct Quantity {
19 pub value: Scalar,
21 pub quantity_type: QuantityType,
23 pub unit: Unit,
25}
26
27impl PartialEq for Quantity {
28 fn eq(&self, other: &Self) -> bool {
29 if self.quantity_type != other.quantity_type {
31 return false;
32 }
33
34 let epsilon = 10.0_f64.powi(-OUTPUT_PRECISION);
36 (self.value - other.value).abs() < epsilon
37 }
38}
39
40impl Quantity {
41 pub fn new(value: Scalar, quantity_type: QuantityType) -> Self {
43 Self {
44 value,
45 unit: quantity_type.base_unit(),
46 quantity_type,
47 }
48 }
49 pub fn map<F>(self, f: F) -> Self
51 where
52 F: FnOnce(Scalar) -> Scalar,
53 {
54 Self {
55 value: f(self.value),
56 quantity_type: self.quantity_type,
57 unit: self.unit,
58 }
59 }
60
61 pub fn scalar(value: Scalar) -> Self {
63 Quantity::new(value, QuantityType::Scalar)
64 }
65
66 pub fn length(length: Scalar) -> Self {
68 Quantity::new(length, QuantityType::Length)
69 }
70
71 pub fn pow(&self, rhs: &Quantity) -> Self {
75 match (&self.quantity_type, &rhs.quantity_type) {
76 (QuantityType::Scalar, QuantityType::Scalar) => {
77 Quantity::new(self.value.powf(rhs.value), QuantityType::Scalar)
78 }
79 _ => todo!(),
80 }
81 }
82
83 pub fn pow_int(&self, rhs: &Integer) -> Self {
87 match &self.quantity_type {
88 QuantityType::Scalar => {
89 Quantity::new(self.value.powi(*rhs as i32), QuantityType::Scalar)
90 }
91 QuantityType::Length => todo!(),
92 QuantityType::Area => todo!(),
93 QuantityType::Volume => todo!(),
94 QuantityType::Density => todo!(),
95 QuantityType::Angle => todo!(),
96 QuantityType::Weight => todo!(),
97 QuantityType::Invalid => todo!(),
98 }
99 }
100}
101
102impl PartialOrd for Quantity {
103 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
104 if self.quantity_type == other.quantity_type {
105 self.value.partial_cmp(&other.value)
106 } else {
107 None
108 }
109 }
110}
111
112impl From<Scalar> for Quantity {
113 fn from(value: Scalar) -> Self {
114 Self::new(value, QuantityType::Scalar)
115 }
116}
117
118impl From<Integer> for Quantity {
119 fn from(value: Integer) -> Self {
120 Self::new(value as Scalar, QuantityType::Scalar)
121 }
122}
123
124impl From<Length> for Quantity {
125 fn from(length: Length) -> Self {
126 Self::new(*length, QuantityType::Length)
127 }
128}
129
130impl Ty for Quantity {
131 fn ty(&self) -> Type {
132 Type::Quantity(self.quantity_type.clone())
133 }
134}
135
136impl std::fmt::Display for Quantity {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 write!(
139 f,
140 "{}{}",
141 round::round(self.unit.denormalize(self.value), OUTPUT_PRECISION),
142 self.unit
143 )
144 }
145}
146
147impl std::hash::Hash for Quantity {
148 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
149 bytemuck::bytes_of(&self.value).hash(state);
150 self.quantity_type.hash(state)
151 }
152}