mech_core/types/
rational_numbers.rs

1use crate::*;
2use super::*;
3
4// Rational Numbers
5// ----------------------------------------------------------------------------
6
7#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, PartialOrd)]
8pub struct R64(pub Rational64);
9
10impl R64 {
11  pub fn new(numer: i64, denom: i64) -> R64 {
12    R64(Rational64::new(numer, denom))
13  }
14
15  pub fn from_le_bytes(bytes: &[u8; 16]) -> R64 {
16    let numer = match bytes[0..8].try_into() {
17      Ok(arr) => i64::from_le_bytes(arr),
18      Err(_) => panic!("Failed to read numerator from bytes"),
19    };
20    let denom = match bytes[8..16].try_into() {
21      Ok(arr) => i64::from_le_bytes(arr),
22      Err(_) => panic!("Failed to read denominator from bytes"),
23    };
24    if denom == 0 {
25      panic!("Denominator cannot be zero");
26    }
27    R64(Rational64::new(numer, denom))
28  }
29
30  pub fn from_f64(f: f64) -> Option<R64> {
31    match Rational64::from_f64(f) {
32      Some(r) => Some(R64(r)),
33      None => None,
34    }
35  }
36
37  pub fn to_f64(&self) -> Option<f64> {
38    match self.0.to_f64() {
39      Some(val) => Some(val),
40      None => None,
41    }
42  }
43
44  pub fn numer(&self) -> &i64 {
45    self.0.numer()
46  }
47
48  pub fn denom(&self) -> &i64 {
49    self.0.denom()
50  }
51}
52
53impl std::fmt::Display for R64 {
54  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55    write!(f, "{}", self.pretty_print())
56  }
57}
58
59
60impl Default for R64 {
61  fn default() -> Self {
62    R64(Rational64::default())
63  }
64}
65
66
67impl PrettyPrint for R64 {
68  fn pretty_print(&self) -> String {
69    format!("{}/{}", self.numer(), self.denom())
70  }
71}
72
73impl Mul<R64> for R64 {
74  type Output = R64;
75  fn mul(self, other: R64) -> R64 {
76    R64(self.0 * other.0)
77  }
78}
79
80impl One for R64 {
81  fn one() -> Self {
82    R64(Rational64::one())
83  }
84  fn is_one(&self) -> bool {
85    self.0.is_one()
86  }
87}
88
89impl Add<R64> for R64 {
90  type Output = R64;
91  fn add(self, other: R64) -> R64 {
92    R64(self.0 + other.0)
93  }
94}
95
96impl AddAssign<R64> for R64 {
97  fn add_assign(&mut self, other: R64) {
98    self.0 += other.0;
99  }
100}
101
102impl Sub<R64> for R64 {
103  type Output = R64;
104  fn sub(self, other: R64) -> R64 {
105    R64(self.0 - other.0)
106  }
107}
108
109impl Div<R64> for R64 {
110  type Output = R64;
111  fn div(self, other: R64) -> R64 {
112    R64(self.0 / other.0)
113  }
114}
115
116impl DivAssign<R64> for R64 {
117  fn div_assign(&mut self, other: R64) {
118    self.0 /= other.0;
119  }
120}
121
122
123impl SubAssign<R64> for R64 {
124  fn sub_assign(&mut self, other: R64) {
125    self.0 -= other.0;
126  }
127}
128
129impl MulAssign<R64> for R64 {
130  fn mul_assign(&mut self, other: R64) {
131    self.0 *= other.0;
132  }
133}
134
135impl Zero for R64 {
136  fn zero() -> Self {
137    R64(Rational64::zero())
138  }
139  fn is_zero(&self) -> bool {
140    self.0.is_zero()
141  }
142}
143
144impl Neg for R64 {
145  type Output = Self;
146  fn neg(self) -> Self::Output {
147    R64(-self.0)
148  }
149}
150
151#[cfg(feature = "f64")]
152impl From<R64> for F64 {
153  fn from(r: R64) -> Self {
154    F64::new(r.0.to_f64().unwrap())
155  }
156}
157
158#[cfg(feature = "f64")]
159impl From<F64> for R64 {
160  fn from(f: F64) -> Self {
161    R64(Rational64::from_f64(f.0).unwrap())
162  }
163}
164
165impl ToUsize for R64 {
166  fn to_usize(&self) -> usize {
167    self.0.to_integer() as usize
168  }
169}
170
171impl ToValue for R64 {
172  fn to_value(&self) -> Value {
173    Value::R64(Ref::new(*self))
174  }
175}