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 solely on the raw total attosecond
154    ///   value (`self.attos` vs `other.attos`).
155    /// - Does **not** perform scale conversion and does not compare anything
156    ///   other than the `attos` field.
157    pub const fn cmp(&self, other: &Self) -> Ordering {
158        if self.attos < other.attos {
159            Ordering::Less
160        } else if self.attos > other.attos {
161            Ordering::Greater
162        } else {
163            Ordering::Equal
164        }
165    }
166
167    /// Returns the smaller of two `Dt`s according to the total physical-time order
168    /// defined by [`Self::cmp`].
169    ///
170    /// This is a `const fn` and can be used in const contexts.
171    #[inline]
172    pub const fn min(self, other: Self) -> Self {
173        match self.cmp(&other) {
174            Ordering::Greater => other,
175            _ => self,
176        }
177    }
178
179    /// Returns the larger of two `Dt`s according to the total physical-time order
180    /// defined by [`Self::cmp`].
181    ///
182    /// See [`Self::min`] for more details.
183    #[inline]
184    pub const fn max(self, other: Self) -> Self {
185        match self.cmp(&other) {
186            Ordering::Less => other,
187            _ => self,
188        }
189    }
190
191    /// True if both sides have the same total attosecond value.
192    ///
193    /// This is a `const fn` so it can be used in const contexts.
194    #[inline(always)]
195    pub const fn eq(&self, other: &Self) -> bool {
196        self.attos == other.attos
197    }
198
199    /// Returns `true` if this `Dt` is less than the other.
200    ///
201    /// This is a `const fn` so it can be used in const contexts.
202    #[inline(always)]
203    pub const fn lt(&self, other: &Self) -> bool {
204        self.attos < other.attos
205    }
206
207    /// Returns `true` if this `Dt` is greater than the other.
208    ///
209    /// This is a `const fn` so it can be used in const contexts.
210    #[inline(always)]
211    pub const fn gt(&self, other: &Self) -> bool {
212        self.attos > other.attos
213    }
214
215    /// Returns `true` if this `Dt` is less than or equal to the other.
216    ///
217    /// This is a `const fn` so it can be used in const contexts.
218    #[inline(always)]
219    pub const fn le(&self, other: &Self) -> bool {
220        self.attos <= other.attos
221    }
222
223    /// Returns `true` if this `Dt` is greater than or equal to the other.
224    ///
225    /// This is a `const fn` so it can be used in const contexts.
226    #[inline(always)]
227    pub const fn ge(&self, other: &Self) -> bool {
228        self.attos >= other.attos
229    }
230}
231
232impl PartialEq for Dt {
233    #[inline]
234    fn eq(&self, other: &Self) -> bool {
235        Dt::eq(self, other)
236    }
237}
238
239impl Eq for Dt {}
240
241impl PartialOrd for Dt {
242    #[inline]
243    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
244        Some(Dt::cmp(self, other))
245    }
246}
247
248impl Ord for Dt {
249    #[inline]
250    fn cmp(&self, other: &Self) -> Ordering {
251        Dt::cmp(self, other)
252    }
253}
254
255impl core::hash::Hash for Dt {
256    /// Hashes the canonical TAI representation so that two `Dt`s that are
257    /// physically equal (after conversion) produce the same hash, regardless of
258    /// the original [`Scale`].
259    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
260        self.attos.hash(state);
261    }
262}