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 Ty for Quantity {
98    fn ty(&self) -> Type {
99        Type::Quantity(self.quantity_type.clone())
100    }
101}
102
103impl std::fmt::Display for Quantity {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        write!(
106            f,
107            "{}{}",
108            round::round(self.value, OUTPUT_PRECISION),
109            self.quantity_type.base_unit()
110        )
111    }
112}
113
114impl std::fmt::Debug for Quantity {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        write!(
117            f,
118            "{} = {}",
119            self.quantity_type,
120            round::round(self.value, OUTPUT_PRECISION)
121        )
122    }
123}
124
125impl std::hash::Hash for Quantity {
126    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
127        bytemuck::bytes_of(&self.value).hash(state);
128        self.quantity_type.hash(state)
129    }
130}