Skip to main content

deep_time/dt/
ops.rs

1use crate::{Dt, Real};
2use core::cmp::Ordering;
3use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5impl Add<Dt> for Dt {
6    type Output = Self;
7
8    #[inline]
9    fn add(self, rhs: Dt) -> Self {
10        Dt::add(&self, rhs)
11    }
12}
13
14impl AddAssign<Dt> for Dt {
15    #[inline]
16    fn add_assign(&mut self, rhs: Dt) {
17        *self = self.add(rhs);
18    }
19}
20
21impl Sub<Dt> for Dt {
22    type Output = Self;
23
24    #[inline]
25    fn sub(self, rhs: Dt) -> Self {
26        Dt::sub(&self, rhs)
27    }
28}
29
30impl SubAssign<Dt> for Dt {
31    #[inline]
32    fn sub_assign(&mut self, rhs: Dt) {
33        *self = self.sub(rhs);
34    }
35}
36
37impl Neg for Dt {
38    type Output = Self;
39
40    /// Negates this `Dt` (returns the additive inverse).
41    #[inline]
42    fn neg(self) -> Self {
43        self.neg()
44    }
45}
46
47impl Mul<i64> for Dt {
48    type Output = Self;
49
50    /// Multiplies this `Dt` by an integer scalar.
51    #[inline]
52    fn mul(self, rhs: i64) -> Self {
53        self.mul(rhs)
54    }
55}
56
57impl MulAssign<i64> for Dt {
58    /// Multiplies this `Dt` by an integer scalar in place.
59    #[inline]
60    fn mul_assign(&mut self, rhs: i64) {
61        *self = self.mul(rhs);
62    }
63}
64
65impl Div<i64> for Dt {
66    type Output = Self;
67
68    /// Divides this `Dt` by an integer scalar.
69    #[inline]
70    fn div(self, rhs: i64) -> Self {
71        self.div(rhs)
72    }
73}
74
75impl DivAssign<i64> for Dt {
76    /// Divides this `Dt` by an integer scalar in place.
77    #[inline]
78    fn div_assign(&mut self, rhs: i64) {
79        *self = self.div(rhs);
80    }
81}
82
83impl Mul<f64> for Dt {
84    type Output = Self;
85
86    #[inline]
87    fn mul(self, rhs: f64) -> Self {
88        self.mul_by_f(rhs)
89    }
90}
91
92impl MulAssign<f64> for Dt {
93    #[inline]
94    fn mul_assign(&mut self, rhs: f64) {
95        *self = self.mul_by_f(rhs);
96    }
97}
98
99impl Div<f64> for Dt {
100    type Output = Self;
101
102    #[inline]
103    fn div(self, rhs: f64) -> Self {
104        self.div_by_f(rhs)
105    }
106}
107
108impl DivAssign<f64> for Dt {
109    #[inline]
110    fn div_assign(&mut self, rhs: f64) {
111        *self = self.div_by_f(rhs);
112    }
113}
114
115impl Mul<Dt> for i64 {
116    type Output = Dt;
117
118    #[inline]
119    fn mul(self, rhs: Dt) -> Dt {
120        rhs.mul(self)
121    }
122}
123
124impl Mul<Dt> for f64 {
125    type Output = Dt;
126
127    #[inline]
128    fn mul(self, rhs: Dt) -> Dt {
129        rhs.mul_by_f(self)
130    }
131}
132
133impl Div<Dt> for Dt {
134    type Output = Real;
135
136    #[inline]
137    fn div(self, rhs: Dt) -> Real {
138        self.div_dt(rhs)
139    }
140}
141
142impl Dt {
143    /// Compares the time values represented by two `Dt`s.
144    ///
145    /// - This comparison is based on the total attosecond value (`self.attos` vs `other.attos`).
146    /// - Does **not** perform scale conversion.
147    pub const fn cmp(&self, other: &Self) -> Ordering {
148        if self.attos < other.attos {
149            Ordering::Less
150        } else if self.attos > other.attos {
151            Ordering::Greater
152        } else {
153            Ordering::Equal
154        }
155    }
156
157    /// Returns the smaller of two `Dt`s according to the total physical-time order
158    /// defined by [`Self::cmp`].
159    ///
160    /// This is a `const fn` and can be used in const contexts.
161    #[inline]
162    pub const fn min(self, other: Self) -> Self {
163        match self.cmp(&other) {
164            Ordering::Greater => other,
165            _ => self,
166        }
167    }
168
169    /// Returns the larger of two `Dt`s according to the total physical-time order
170    /// defined by [`Self::cmp`].
171    ///
172    /// See [`Self::min`] for more details.
173    #[inline]
174    pub const fn max(self, other: Self) -> Self {
175        match self.cmp(&other) {
176            Ordering::Less => other,
177            _ => self,
178        }
179    }
180
181    /// True if both sides have the same total attosecond value.
182    ///
183    /// This is a `const fn` so it can be used in const contexts.
184    #[inline(always)]
185    pub const fn eq(&self, other: &Self) -> bool {
186        self.attos == other.attos
187    }
188
189    /// Returns `true` if this `Dt` is less than the other.
190    ///
191    /// This is a `const fn` so it can be used in const contexts.
192    #[inline(always)]
193    pub const fn lt(&self, other: &Self) -> bool {
194        self.attos < other.attos
195    }
196
197    /// Returns `true` if this `Dt` is greater than the other.
198    ///
199    /// This is a `const fn` so it can be used in const contexts.
200    #[inline(always)]
201    pub const fn gt(&self, other: &Self) -> bool {
202        self.attos > other.attos
203    }
204
205    /// Returns `true` if this `Dt` is less than or equal to the other.
206    ///
207    /// This is a `const fn` so it can be used in const contexts.
208    #[inline(always)]
209    pub const fn le(&self, other: &Self) -> bool {
210        self.attos <= other.attos
211    }
212
213    /// Returns `true` if this `Dt` is greater than or equal to the other.
214    ///
215    /// This is a `const fn` so it can be used in const contexts.
216    #[inline(always)]
217    pub const fn ge(&self, other: &Self) -> bool {
218        self.attos >= other.attos
219    }
220}
221
222impl PartialEq for Dt {
223    #[inline]
224    fn eq(&self, other: &Self) -> bool {
225        Dt::eq(self, other)
226    }
227}
228
229impl Eq for Dt {}
230
231impl PartialOrd for Dt {
232    #[inline]
233    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
234        Some(Dt::cmp(self, other))
235    }
236}
237
238impl Ord for Dt {
239    #[inline]
240    fn cmp(&self, other: &Self) -> Ordering {
241        Dt::cmp(self, other)
242    }
243}
244
245impl core::hash::Hash for Dt {
246    /// Hashes the canonical TAI representation so that two `Dt`s that are
247    /// physically equal (after conversion) produce the same hash, regardless of
248    /// the original [`Scale`].
249    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
250        self.attos.hash(state);
251    }
252}