Skip to main content

microcad_lang/value/quantity/
ops.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Quantity binery operators module.
5
6use microcad_core::{Integer, Scalar};
7
8use crate::{ty::*, value::*};
9
10impl std::ops::Neg for Quantity {
11    type Output = Quantity;
12
13    fn neg(self) -> Self::Output {
14        self.map(|v| -v)
15    }
16}
17
18impl std::ops::Add for Quantity {
19    type Output = QuantityResult;
20
21    fn add(self, rhs: Self) -> Self::Output {
22        if self.quantity_type == rhs.quantity_type {
23            Ok(Quantity::new(self.value + rhs.value, self.quantity_type))
24        } else {
25            Err(QuantityError::InvalidOperation(self, '+', rhs))
26        }
27    }
28}
29
30impl std::ops::Add<Integer> for Quantity {
31    type Output = QuantityResult;
32
33    fn add(self, rhs: Integer) -> Self::Output {
34        if self.quantity_type == QuantityType::Scalar {
35            Ok(Quantity::new(
36                self.value + rhs as Scalar,
37                self.quantity_type,
38            ))
39        } else {
40            Err(QuantityError::InvalidOperation(self, '+', rhs.into()))
41        }
42    }
43}
44
45impl std::ops::Add<Quantity> for Integer {
46    type Output = QuantityResult;
47
48    fn add(self, rhs: Quantity) -> Self::Output {
49        if rhs.quantity_type == QuantityType::Scalar {
50            Ok(Quantity::new(self as Scalar + rhs.value, rhs.quantity_type))
51        } else {
52            Err(QuantityError::InvalidOperation(self.into(), '+', rhs))
53        }
54    }
55}
56
57impl std::ops::Sub for Quantity {
58    type Output = QuantityResult;
59
60    fn sub(self, rhs: Self) -> Self::Output {
61        if self.quantity_type == rhs.quantity_type {
62            Ok(Quantity::new(self.value - rhs.value, self.quantity_type))
63        } else {
64            Err(QuantityError::InvalidOperation(self, '-', rhs))
65        }
66    }
67}
68
69impl std::ops::Sub<Integer> for Quantity {
70    type Output = QuantityResult;
71
72    fn sub(self, rhs: Integer) -> Self::Output {
73        if self.quantity_type == QuantityType::Scalar {
74            Ok(Quantity::new(
75                self.value - rhs as Scalar,
76                self.quantity_type,
77            ))
78        } else {
79            Err(QuantityError::InvalidOperation(self, '-', rhs.into()))
80        }
81    }
82}
83
84impl std::ops::Sub<Quantity> for Integer {
85    type Output = QuantityResult;
86
87    fn sub(self, rhs: Quantity) -> Self::Output {
88        if rhs.quantity_type == QuantityType::Scalar {
89            Ok(Quantity::new(self as Scalar - rhs.value, rhs.quantity_type))
90        } else {
91            Err(QuantityError::InvalidOperation(self.into(), '-', rhs))
92        }
93    }
94}
95
96impl std::ops::Mul for Quantity {
97    type Output = QuantityResult;
98
99    fn mul(self, rhs: Self) -> Self::Output {
100        let t = self.quantity_type.clone() * rhs.quantity_type.clone();
101        if t == QuantityType::Invalid {
102            Err(QuantityError::InvalidOperation(self, '*', rhs))
103        } else {
104            Ok(Self::new(self.value * rhs.value, t))
105        }
106    }
107}
108
109impl std::ops::Mul<Integer> for Quantity {
110    type Output = QuantityResult;
111
112    fn mul(self, rhs: Integer) -> Self::Output {
113        self * Into::<Quantity>::into(rhs)
114    }
115}
116
117impl std::ops::Mul<Quantity> for Integer {
118    type Output = QuantityResult;
119
120    fn mul(self, rhs: Quantity) -> Self::Output {
121        Into::<Quantity>::into(self) * rhs
122    }
123}
124
125impl std::ops::Div for Quantity {
126    type Output = QuantityResult;
127
128    fn div(self, rhs: Self) -> Self::Output {
129        let t = self.quantity_type.clone() / rhs.quantity_type.clone();
130        if t == QuantityType::Invalid {
131            Err(QuantityError::InvalidOperation(self, '/', rhs))
132        } else {
133            Ok(Self::new(self.value / rhs.value, t))
134        }
135    }
136}
137
138impl std::ops::Div<Integer> for Quantity {
139    type Output = QuantityResult;
140
141    fn div(self, rhs: Integer) -> Self::Output {
142        self / Into::<Quantity>::into(rhs)
143    }
144}
145
146impl std::ops::Div<Quantity> for Integer {
147    type Output = QuantityResult;
148
149    fn div(self, rhs: Quantity) -> Self::Output {
150        Into::<Quantity>::into(self) / rhs
151    }
152}