arkley_numerics/
number.rs

1use std::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
2
3use arkley_traits::Power;
4
5use crate::{StandardForm,ParsingNumberError};
6
7/// Represents a numeric value that can be decimal (aka f64) or Fraction or Standardform number
8///
9/// `Note` : add fractions variant to is as well 
10#[derive(Debug,PartialEq)]
11pub enum Number {
12    /// Represents a floating-point decimal number.
13    Decimal(f64),
14    /// Represents a number in the StandardForm notation.
15    StandardForm(StandardForm),
16}
17
18impl PartialOrd<Number> for Number {
19    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
20        match (self, other) {
21            (Number::Decimal(a), Number::Decimal(b)) => a.partial_cmp(b),
22            (Number::StandardForm(a), Number::StandardForm(b)) => a.partial_cmp(b),
23            (Number::StandardForm(a), Number::Decimal(b)) => a.partial_cmp(b),
24            (Number::Decimal(a), Number::StandardForm(b)) => {
25                let rhs : StandardForm = (*a).into();
26                rhs.partial_cmp(b)
27            },
28        }
29    }
30}
31
32impl std::fmt::Display for Number {
33    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34        match self {
35            Number::Decimal(float) => write!(f,"{}",float),
36            Number::StandardForm(sf) => write!(f,"{}",sf),
37        }
38    }
39}
40
41impl TryFrom<&str> for Number {
42    type Error = ParsingNumberError;
43    fn try_from(value : &str) -> Result<Self, Self::Error> {
44        let into_f64 = value.parse::<f64>();
45        if let Ok(float) = into_f64 {
46            return Ok(Number::Decimal(float));
47        }
48
49        let into_sf = StandardForm::try_from(value);
50
51        if let Ok(standard_form) = into_sf{
52            return Ok(Number::StandardForm(standard_form));
53        }
54
55        Err(ParsingNumberError(into_f64.unwrap_err(),into_sf.unwrap_err()))
56    }
57}
58
59impl Power for Number {
60    type Output = Number;
61
62    fn to_the_power_of(self, other: Number) -> Self::Output {
63        match (self, other) {
64            (Number::Decimal(a), Number::Decimal(b)) => Number::Decimal(a.to_the_power_of(b)),
65            _ => todo!("")
66        }
67    }
68}
69
70impl Add for Number {
71    type Output = Number;
72
73    fn add(self,other : Number) -> Self::Output {
74        use crate::Number::Decimal;
75        match (self,other) {
76            (Decimal(f1),Decimal(f2)) => Decimal(f1 + f2),
77            (Number::StandardForm(sf1),Number::StandardForm(sf2)) => Number::StandardForm(sf1 + sf2),
78            (Number::StandardForm(sf1),Number::Decimal(f2)) => Number::StandardForm(sf1 + f2),
79            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
80                let rhs : StandardForm = f1.into();
81                Number::StandardForm(rhs + sf2)
82            }
83        }
84    }
85}
86
87impl Sub for Number {
88    type Output = Number;
89
90    fn sub(self,other : Number) -> Self::Output {
91        match (self,other) {
92            (Number::Decimal(f1),Number::Decimal(f2)) => Number::Decimal(f1 - f2),
93            (Number::StandardForm(sf1),Number::StandardForm(sf2)) => Number::StandardForm(sf1 - sf2),
94            (Number::StandardForm(sf1),Number::Decimal(f2)) => Number::StandardForm(sf1 - f2),
95            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
96                let rhs : StandardForm = f1.into();
97                Number::StandardForm(rhs - sf2)
98            }
99        }
100    }
101}
102
103impl Mul for Number {
104    type Output = Number;
105
106    fn mul(self,other : Number) -> Self::Output {
107        match (self,other) {
108            (Number::Decimal(f1),Number::Decimal(f2)) => Number::Decimal(f1 * f2),
109            (Number::StandardForm(sf1),Number::StandardForm(sf2)) => Number::StandardForm(sf1 * sf2),
110            (Number::StandardForm(sf1),Number::Decimal(f2)) => Number::StandardForm(sf1 * f2),
111            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
112                let rhs : StandardForm = f1.into();
113                Number::StandardForm(rhs * sf2)
114            }
115        }
116    }
117}
118
119impl Div for Number {
120    type Output = Number;
121
122    fn div(self,other : Number) -> Self::Output {
123        use crate::Number::Decimal;
124        match (self,other) {
125            (Decimal(f1),Decimal(f2)) => Number::Decimal(f1 / f2),
126            (Number::StandardForm(sf1),Number::StandardForm(sf2)) => Number::StandardForm(sf1 / sf2),
127            (Number::StandardForm(sf1),Number::Decimal(f2)) => Number::StandardForm(sf1 / f2),
128            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
129                let rhs : StandardForm = f1.into();
130                Number::StandardForm(rhs / sf2)
131            }
132        }
133    }
134}
135
136impl AddAssign for Number {
137    fn add_assign(&mut self, other: Number) {
138        let temp_self = std::mem::replace(self, Number::Decimal(0.0)); // Take ownership of self
139
140        match (temp_self, other) {
141            (Number::Decimal(f1), Number::Decimal(f2)) => *self = Number::Decimal(f1 + f2),
142            (Number::StandardForm(sf1), Number::StandardForm(sf2)) => *self = Number::StandardForm(sf1 + sf2),
143            (Number::StandardForm(sf1), Number::Decimal(f2)) => *self = Number::StandardForm(sf1 + f2),
144            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
145                let rhs: StandardForm = (f1).into();
146                *self = Number::StandardForm(rhs + sf2);
147            }
148        }
149    }
150}
151
152impl SubAssign for Number {
153    fn sub_assign(&mut self, other: Number) {
154        let temp_self = std::mem::replace(self, Number::Decimal(0.0)); // Take ownership of self
155
156        match (temp_self, other) {
157            (Number::Decimal(f1), Number::Decimal(f2)) => *self = Number::Decimal(f1 - f2),
158            (Number::StandardForm(sf1), Number::StandardForm(sf2)) => *self = Number::StandardForm(sf1 - sf2),
159            (Number::StandardForm(sf1), Number::Decimal(f2)) => *self = Number::StandardForm(sf1 - f2),
160            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
161                let rhs: StandardForm = (f1).into();
162                *self = Number::StandardForm(rhs - sf2);
163            }
164        }
165    }
166}
167
168impl MulAssign for Number {
169    fn mul_assign(&mut self, other: Number) {
170        let temp_self = std::mem::replace(self, Number::Decimal(0.0)); // Take ownership of self
171
172        match (temp_self, other) {
173            (Number::Decimal(f1), Number::Decimal(f2)) => *self = Number::Decimal(f1 * f2),
174            (Number::StandardForm(sf1), Number::StandardForm(sf2)) => *self = Number::StandardForm(sf1 * sf2),
175            (Number::StandardForm(sf1), Number::Decimal(f2)) => *self = Number::StandardForm(sf1 * f2),
176            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
177                let rhs: StandardForm = (f1).into();
178                *self = Number::StandardForm(rhs * sf2);
179            }
180        }
181    }
182}
183
184impl DivAssign for Number {
185    fn div_assign(&mut self, other: Number) {
186        let temp_self = std::mem::replace(self, Number::Decimal(0.0)); // Take ownership of self
187        match (temp_self, other) {
188            (Number::Decimal(f1), Number::Decimal(f2)) => *self = Number::Decimal(f1 / f2),
189            (Number::StandardForm(sf1), Number::StandardForm(sf2)) => *self = Number::StandardForm(sf1 / sf2),
190            (Number::StandardForm(sf1), Number::Decimal(f2)) => *self = Number::StandardForm(sf1 / f2),
191            (Number::Decimal(f1), Number::StandardForm(sf2)) => {
192                let rhs: StandardForm = (f1).into();
193                *self = Number::StandardForm(rhs / sf2);
194            }
195        }
196    }
197}
198
199macro_rules! primitives {
200    (eq => $($t : ty),*) => {
201        $(
202            impl PartialEq<$t> for Number {
203                fn eq(&self, other: &$t) -> bool {
204                    match self {
205                        Number::Decimal(f) => f == &(*other as f64),
206                        Number::StandardForm(sf) => sf == other,
207                    }
208                }
209            }
210        )*
211    };
212    (ord => $($t : ty),*) => {
213        $(
214            impl PartialOrd<$t> for Number {
215                fn partial_cmp(&self, other: &$t) -> Option<std::cmp::Ordering> {
216                    match self {
217                        Number::Decimal(f) => f.partial_cmp(&(*other as f64)),
218                        Number::StandardForm(sf) => sf.partial_cmp(other)
219                    }
220                }
221            }
222        )*
223    };
224
225    (add => $($t : ty),*) => {
226        $(
227            impl Add<$t> for Number {
228                type Output = Self;
229                fn add(self, other: $t) -> Self {
230                    match self {
231                        Number::Decimal(f) => Number::Decimal(f + other as f64),
232                        Number::StandardForm(sf) => Number::StandardForm(sf + other),
233                    }
234                }
235            }
236            
237            impl AddAssign<$t> for Number {
238                fn add_assign(&mut self, other: $t) {
239                    *self += Number::Decimal(other as f64)
240                }
241            }
242        )*
243    };
244
245    (sub => $($t : ty),*) => {
246        $(
247            impl Sub<$t> for Number {
248                type Output = Self;
249                fn sub(self, other: $t) -> Self {
250                    match self {
251                        Number::Decimal(f) => Number::Decimal(f - other as f64),
252                        Number::StandardForm(sf) => Number::StandardForm(sf - other),
253                    }
254                }
255            }
256            
257            impl SubAssign<$t> for Number {
258                fn sub_assign(&mut self, other: $t) {
259                    *self -= Number::Decimal(other as f64)
260                }
261            }
262        )*
263    };
264    (mul => $($t : ty),*) => {
265        $(
266            impl Mul<$t> for Number {
267                type Output = Self;
268                fn mul(self, other: $t) -> Self {
269                    match self {
270                        Number::Decimal(f) => Number::Decimal(f * other as f64),
271                        Number::StandardForm(sf) => Number::StandardForm(sf * other),
272                    }
273                }
274            }
275            
276            impl MulAssign<$t> for Number {
277                fn mul_assign(&mut self, other: $t) {
278                    *self *= Number::Decimal(other as f64)
279                }
280            }
281        )*
282    };
283    (div => $($t : ty),*) => {
284        $(
285            impl Div<$t> for Number {
286                type Output = Self;
287                fn div(self, other: $t) -> Self {
288                    match self {
289                        Number::Decimal(f) => Number::Decimal(f / other as f64),
290                        Number::StandardForm(sf) => Number::StandardForm(sf / other),
291                    }
292                }
293            }
294            
295            impl DivAssign<$t> for Number {
296                fn div_assign(&mut self, other: $t) {
297                    *self /= Number::Decimal(other as f64)
298                }
299            }
300        )*
301    };
302    (operations => $($t:ty),*) => {
303        $(
304            primitives!(add => $t);
305            primitives!(sub => $t);
306            primitives!(mul => $t);
307            primitives!(div => $t);
308        )*
309    }
310}
311
312primitives!(eq => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
313primitives!(ord => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
314primitives!(operations => i8, i16, i32, i64, u8, u16, u32, u64,f32,f64);
315
316#[cfg(test)]
317mod test {
318    use super::*;
319    #[test]
320    fn test_addition() {
321        let num1 = Number::Decimal(2.5);
322        let num2 = Number::Decimal(3.5);
323        let result = num1 + num2;
324        assert_eq!(result, Number::Decimal(6.0));
325    }
326
327    // Test subtraction
328    #[test]
329    fn test_subtraction() {
330        let num1 = Number::Decimal(5.5);
331        let num2 = Number::Decimal(3.5);
332        let result = num1 - num2;
333        assert_eq!(result, Number::Decimal(2.0));
334    }
335
336    // Test multiplication
337    #[test]
338    fn test_multiplication() {
339        let num1 = Number::Decimal(2.5);
340        let num2 = Number::Decimal(3.0);
341        let result = num1 * num2;
342        assert_eq!(result, Number::Decimal(7.5));
343    }
344
345    // Test division
346    #[test]
347    fn test_division() {
348        let num1 = Number::Decimal(10.0);
349        let num2 = Number::Decimal(2.0);
350        let result = num1 / num2;
351        assert_eq!(result, Number::Decimal(5.0));
352    }
353
354    // Test addition assignment
355    #[test]
356    fn test_addition_assignment() {
357        let mut num = Number::Decimal(3.0);
358        let num2 = Number::Decimal(2.0);
359        num += num2;
360        assert_eq!(num, Number::Decimal(5.0));
361    }
362
363    // Test subtraction assignment
364    #[test]
365    fn test_subtraction_assignment() {
366        let mut num = Number::Decimal(5.0);
367        let num2 = Number::Decimal(3.0);
368        num -= num2;
369        assert_eq!(num, Number::Decimal(2.0));
370    }
371
372    // Test multiplication assignment
373    #[test]
374    fn test_multiplication_assignment() {
375        let mut num = Number::Decimal(2.5);
376        let num2 = Number::Decimal(3.0);
377        num *= num2;
378        assert_eq!(num, Number::Decimal(7.5));
379    }
380
381    // Test division assignment
382    #[test]
383    fn test_division_assignment() {
384        let mut num = Number::Decimal(10.0);
385        let num2 = Number::Decimal(2.0);
386        num /= num2;
387        assert_eq!(num, Number::Decimal(5.0));
388    }
389
390    #[test]
391    fn test_display_decimal() {
392        let number = Number::Decimal(3.14);
393        assert_eq!(format!("{}", number), "3.14");
394        assert_eq!(number.to_string(), "3.14");
395    }
396
397    #[test]
398    fn test_try_from_valid_number() {
399        // Test a valid number conversion
400        let input = "3.14";
401        let result = Number::try_from(input);
402        assert!(result.is_ok());
403
404        // Check if the correct variant and value are returned
405        if let Ok(Number::Decimal(value)) = result {
406            assert_eq!(value, 3.14);
407        } else {
408            assert!(false, "Expected Ok(Number::Decimal(_)), but got an error.");
409        }
410    }
411
412    #[test]
413    fn test_try_from_invalid_number() {
414        // Test an invalid number conversion
415        let input = "abc"; // This is not a valid floating-point number
416        let result = Number::try_from(input);
417        assert!(result.is_err());
418
419        // Check if the correct error variant is returned
420        if let Err(_) = result {
421        } else {
422            assert!(false, "Expected Err(ParseFloatError), but got a success.");
423        }
424    }
425
426    #[test]
427    fn test_try_from_empty_string() {
428        // Test conversion from an empty string
429        let input = "";
430        let result = Number::try_from(input);
431        assert!(result.is_err());
432
433        // Check if the correct error variant is returned
434        if let Err(_) = result {
435        } else {
436            assert!(false, "Expected Err(ParseFloatError), but got a success.");
437        }
438    }
439}