Skip to main content

deep_time/dt/
ops.rs

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