microcad_lang/value/quantity/
mod.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Matrix value type
5
6pub mod error;
7pub mod ops;
8
9use crate::ty::*;
10use microcad_core::*;
11
12pub use error::*;
13
14const OUTPUT_PRECISION: i32 = 14;
15
16/// A numeric value
17#[derive(Clone, PartialEq)]
18pub struct Quantity {
19    /// The numeric value of the quantity.
20    pub value: Scalar,
21    /// The quantity type with a base unit.
22    pub quantity_type: QuantityType,
23}
24
25impl Quantity {
26    /// Create a new quantity.
27    pub fn new(value: Scalar, quantity_type: QuantityType) -> Self {
28        Self {
29            value,
30            quantity_type,
31        }
32    }
33
34    /// Create a new Scalar quantity.
35    pub fn scalar(value: Scalar) -> Self {
36        Quantity::new(value, QuantityType::Scalar)
37    }
38
39    /// Create a new Length quantity in millimeters.
40    pub fn length(length: Scalar) -> Self {
41        Quantity::new(length, QuantityType::Length)
42    }
43
44    /// Calculate the power of quantity.
45    ///
46    /// *Note: This function has not been implemented completely.*
47    pub fn pow(&self, rhs: &Quantity) -> Self {
48        match (&self.quantity_type, &rhs.quantity_type) {
49            (QuantityType::Scalar, QuantityType::Scalar) => {
50                Quantity::new(self.value.powf(rhs.value), QuantityType::Scalar)
51            }
52            _ => todo!(),
53        }
54    }
55
56    /// Calculate the power of quantity and an integer.
57    ///
58    /// *Note: This function has not been implemented completely.*
59    pub fn pow_int(&self, rhs: &Integer) -> Self {
60        match &self.quantity_type {
61            QuantityType::Scalar => {
62                Quantity::new(self.value.powi(*rhs as i32), QuantityType::Scalar)
63            }
64            QuantityType::Length => todo!(),
65            QuantityType::Area => todo!(),
66            QuantityType::Volume => todo!(),
67            QuantityType::Density => todo!(),
68            QuantityType::Angle => todo!(),
69            QuantityType::Weight => todo!(),
70            QuantityType::Invalid => todo!(),
71        }
72    }
73}
74
75impl PartialOrd for Quantity {
76    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
77        if self.quantity_type == other.quantity_type {
78            self.value.partial_cmp(&other.value)
79        } else {
80            None
81        }
82    }
83}
84
85impl From<Scalar> for Quantity {
86    fn from(value: Scalar) -> Self {
87        Self::new(value, QuantityType::Scalar)
88    }
89}
90
91impl From<Integer> for Quantity {
92    fn from(value: Integer) -> Self {
93        Self::new(value as Scalar, QuantityType::Scalar)
94    }
95}
96
97impl From<Length> for Quantity {
98    fn from(length: Length) -> Self {
99        Self::new(*length, QuantityType::Length)
100    }
101}
102
103impl Ty for Quantity {
104    fn ty(&self) -> Type {
105        Type::Quantity(self.quantity_type.clone())
106    }
107}
108
109impl std::fmt::Display for Quantity {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        write!(
112            f,
113            "{}{}",
114            round::round(self.value, OUTPUT_PRECISION),
115            self.quantity_type.base_unit()
116        )
117    }
118}
119
120impl std::fmt::Debug for Quantity {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        write!(
123            f,
124            "{} = {}",
125            self.quantity_type,
126            round::round(self.value, OUTPUT_PRECISION)
127        )
128    }
129}
130
131impl std::hash::Hash for Quantity {
132    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
133        bytemuck::bytes_of(&self.value).hash(state);
134        self.quantity_type.hash(state)
135    }
136}