1use std::ops::{Add,Sub,Mul,Div,Rem,AddAssign,SubAssign,MulAssign,DivAssign,RemAssign,Neg};
2use std::cmp::Ordering;
3
4use standardform::StandardForm;
5use fraction::GenericFraction;
6
7use crate::ParsingNumberError;
8
9#[derive(Debug,Clone,PartialEq,PartialOrd)]
14pub enum Number {
15 Decimal(f64),
17
18 StandardForm(StandardForm),
20
21 Fraction(GenericFraction<u32>)
23}
24
25impl std::fmt::Display for Number {
26 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
27 match self {
28 Number::Decimal(d) => write!(f,"{d}"),
29 Number::StandardForm(sf) => write!(f,"{sf}"),
30 Number::Fraction(fr) => write!(f,"{fr}"),
31 }
32 }
33}
34
35impl From<StandardForm> for Number {
36 fn from(value: StandardForm) -> Self {
37 Number::StandardForm(value)
38 }
39}
40
41impl From<GenericFraction<u32>> for Number {
42 fn from(value: GenericFraction<u32>) -> Self {
43 Number::Fraction(value)
44 }
45}
46
47impl From<f64> for Number {
48 fn from(value: f64) -> Self {
49 Number::Decimal(value)
50 }
51}
52
53impl From<Number> for f64 {
54 fn from(value: Number) -> Self {
55 match value {
56 Number::Decimal(d) => d,
57 Number::StandardForm(sf) => sf.into(),
58 Number::Fraction(fr) => match fr {
59 GenericFraction::Rational(sign,ratio) => match sign.is_positive() {
60 true => ratio.to_integer() as f64 ,
61 false => -(ratio.to_integer() as f64)
62 },
63 GenericFraction::Infinity(sign) => match sign.is_positive() {
64 true => f64::INFINITY,
65 false => -f64::INFINITY
66 },
67 GenericFraction::NaN => f64::NAN,
68 },
69 }
70 }
71}
72impl TryFrom<&str> for Number {
73 type Error = ParsingNumberError;
74 fn try_from(value : &str) -> Result<Self, Self::Error> {
75
76 let try_into_f64 = value.parse::<f64>();
77
78 if let Ok(double) = try_into_f64 {
79 return Ok(Number::Decimal(double));
80 }
81
82 let try_into_fraction = value.parse::<GenericFraction<u32>>();
83
84 if let Ok(fraction) = try_into_fraction {
85 return Ok(Number::Fraction(fraction));
86 }
87
88 let try_into_sf = StandardForm::try_from(value);
89
90 if let Ok(sf) = try_into_sf {
91 return Ok(Number::StandardForm(sf));
92 }
93
94 Err(ParsingNumberError::new(
95 try_into_fraction.unwrap_err(),
96 try_into_f64.unwrap_err(),
97 try_into_sf.unwrap_err()
98 ))
99 }
100}
101
102impl Neg for Number {
103 type Output = Self;
104 fn neg(self) -> Self::Output {
105 match self {
106 Number::Decimal(d) => Number::Decimal(-d),
107 Number::StandardForm(sf) => Number::StandardForm(-sf),
108 Number::Fraction(fr) => Number::Fraction(-fr),
109 }
110 }
111}
112
113impl Eq for Number {}
114
115impl Ord for Number {
116 fn cmp(&self, other: &Self) -> Ordering {
117 self.partial_cmp(other).unwrap()
118 }
119}
120
121
122fn from_fraction_rational_to_sf(sign : fraction::Sign,ratio : fraction::Ratio<u32>) -> StandardForm {
123 let (mantissa,exponent) = (match sign{
124 fraction::Sign::Plus => *ratio.numer() as f64,
125 fraction::Sign::Minus => -(*ratio.numer() as f64)
126 }, -(ratio.denom().trailing_zeros() as i8));
127 StandardForm::new(mantissa,exponent)
128}
129
130
131impl Add for Number {
132 type Output = Number;
133
134 fn add(self,other : Number) -> Self::Output {
135 use crate::Number::*;
136 match (self,other) {
137 (Decimal(d1),Decimal(d2)) => (d1 + d2).into(),
138 (Decimal(d),StandardForm(sf)) => (sf + d).into(),
139 (Decimal(d),Fraction(fr)) => (fr + d).into(),
140
141 (StandardForm(sf1),StandardForm(sf2)) => (sf1 + sf2).into(),
142 (StandardForm(sf),Decimal(d)) => (sf + d).into(),
143 (StandardForm(sf),Fraction(fr)) => match fr {
144 GenericFraction::Rational(sign,ratio) => (sf + from_fraction_rational_to_sf(sign,ratio)).into(),
145 _ => fr.into()
146 },
147
148 (Fraction(fr1),Fraction(fr2)) => (fr1 + fr2).into(),
149 (Fraction(fr),Decimal(d)) => (fr + d).into(),
150 (Fraction(fr),StandardForm(sf)) => match fr {
151 GenericFraction::Rational(sign,ratio) => (from_fraction_rational_to_sf(sign,ratio) + sf).into(),
152 _ => fr.into()
153 },
154 }
155 }
156}
157
158impl Sub for Number {
159 type Output = Number;
160
161 fn sub(self,other : Number) -> Self::Output {
162 use crate::Number::*;
163 match (self,other) {
164 (Decimal(d1),Decimal(d2)) => (d1 - d2).into(),
165 (Decimal(d),StandardForm(sf)) => (sf - d).into(),
166 (Decimal(d),Fraction(fr)) => (fr - d).into(),
167
168 (StandardForm(sf1),StandardForm(sf2)) => (sf1 - sf2).into(),
169 (StandardForm(sf),Decimal(d)) => (sf - d).into(),
170 (StandardForm(sf),Fraction(fr)) => match fr {
171 GenericFraction::Rational(sign,ratio) => (sf - from_fraction_rational_to_sf(sign,ratio)).into(),
172 _ => fr.into()
173 },
174
175 (Fraction(fr1),Fraction(fr2)) => (fr1 - fr2).into(),
176 (Fraction(fr),Decimal(d)) => (fr - d).into(),
177 (Fraction(fr),StandardForm(sf)) => match fr {
178 GenericFraction::Rational(sign,ratio) => (from_fraction_rational_to_sf(sign,ratio) - sf).into(),
179 _ => fr.into()
180 },
181 }
182 }
183}
184
185impl Mul for Number {
186 type Output = Number;
187
188 fn mul(self,other : Number) -> Self::Output {
189 use crate::Number::*;
190 match (self,other) {
191 (Decimal(d1),Decimal(d2)) => (d1 * d2).into(),
192 (Decimal(d),StandardForm(sf)) => (sf * d).into(),
193 (Decimal(d),Fraction(fr)) => (fr * d).into(),
194
195 (StandardForm(sf1),StandardForm(sf2)) => (sf1 * sf2).into(),
196 (StandardForm(sf),Decimal(d)) => (sf * d).into(),
197 (StandardForm(sf),Fraction(fr)) => match fr {
198 GenericFraction::Rational(sign,ratio) => (sf * from_fraction_rational_to_sf(sign,ratio)).into(),
199 _ => fr.into()
200 },
201
202 (Fraction(fr1),Fraction(fr2)) => (fr1 * fr2).into(),
203 (Fraction(fr),Decimal(d)) => (fr * d).into(),
204 (Fraction(fr),StandardForm(sf)) => match fr {
205 GenericFraction::Rational(sign,ratio) => (from_fraction_rational_to_sf(sign,ratio) * sf).into(),
206 _ => fr.into()
207 },
208 }
209 }
210}
211
212impl Div for Number {
213 type Output = Number;
214
215 fn div(self,other : Number) -> Self::Output {
216 use crate::Number::*;
217 match (self,other) {
218 (Decimal(d1),Decimal(d2)) => (d1 / d2).into(),
219 (Decimal(d),StandardForm(sf)) => (sf / d).into(),
220 (Decimal(d),Fraction(fr)) => (fr / d).into(),
221
222 (StandardForm(sf1),StandardForm(sf2)) => (sf1 / sf2).into(),
223 (StandardForm(sf),Decimal(d)) => (sf / d).into(),
224 (StandardForm(sf),Fraction(fr)) => match fr {
225 GenericFraction::Rational(sign,ratio) => (sf / from_fraction_rational_to_sf(sign,ratio)).into(),
226 _ => fr.into()
227 },
228
229 (Fraction(fr1),Fraction(fr2)) => (fr1 / fr2).into(),
230 (Fraction(fr),Decimal(d)) => (fr / d).into(),
231 (Fraction(fr),StandardForm(sf)) => match fr {
232 GenericFraction::Rational(sign,ratio) => (from_fraction_rational_to_sf(sign,ratio) / sf).into(),
233 _ => fr.into()
234 },
235 }
236 }
237}
238
239impl Rem for Number {
240 type Output = Number;
241
242 fn rem(self,other : Number) -> Self::Output {
243 use crate::Number::*;
244 match (self,other) {
245 (Decimal(d1),Decimal(d2)) => (d1 % d2).into(),
246 (Decimal(d),StandardForm(sf)) => (sf % d).into(),
247 (Decimal(d),Fraction(fr)) => (fr % d).into(),
248
249 (StandardForm(sf1),StandardForm(sf2)) => (sf1 % sf2).into(),
250 (StandardForm(sf),Decimal(d)) => (sf % d).into(),
251 (StandardForm(sf),Fraction(fr)) => match fr {
252 GenericFraction::Rational(sign,ratio) => (sf % from_fraction_rational_to_sf(sign,ratio)).into(),
253 _ => fr.into()
254 },
255
256 (Fraction(fr1),Fraction(fr2)) => (fr1 % fr2).into(),
257 (Fraction(fr),Decimal(d)) => (fr % d).into(),
258 (Fraction(fr),StandardForm(sf)) => match fr {
259 GenericFraction::Rational(sign,ratio) => (from_fraction_rational_to_sf(sign,ratio) % sf).into(),
260 _ => fr.into()
261 },
262 }
263 }
264}
265
266impl AddAssign for Number {
267 fn add_assign(&mut self, other: Number) {
268 *self = self.clone() + other;
269 }
270}
271
272impl SubAssign for Number {
273 fn sub_assign(&mut self, other: Number) {
274 *self = self.clone() - other;
275 }
276}
277
278impl MulAssign for Number {
279 fn mul_assign(&mut self, other: Number) {
280 *self = self.clone() * other;
281 }
282}
283
284impl DivAssign for Number {
285 fn div_assign(&mut self, other: Number) {
286 *self = self.clone() / other;
287 }
288}
289
290impl RemAssign for Number {
291 fn rem_assign(&mut self, other: Number) {
292 *self = self.clone() % other;
293 }
294}
295
296
297macro_rules! primitives {
298 (eq => $($t : ty),*) => {
299 $(
300 impl PartialEq<$t> for Number {
301 fn eq(&self, other: &$t) -> bool {
302 match self {
303 Number::Decimal(d) => d == &(*other as f64),
304 Number::StandardForm(sf) => {
305 let xy : StandardForm = (*other).into();
306 sf == &xy
307 },
308 Number::Fraction(fr) => {
309 let xy : GenericFraction<u32> = (*other).into();
310 fr == &xy
311 }
312 }
313 }
314 }
315 )*
316 };
317 (ord => $($t : ty),*) => {
318 $(
319 impl PartialOrd<$t> for Number {
320 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
321 match self {
322 Number::Decimal(f) => f.partial_cmp(&(*other as f64)),
323 Number::StandardForm(sf) => {
324 let xy : StandardForm = (*other).into();
325 sf.partial_cmp(&xy)
326 },
327 Number::Fraction(fr) => {
328 let xy : GenericFraction<u32> = (*other).into();
329 fr.partial_cmp(&xy)
330 }
331 }
332 }
333 }
334 )*
335 };
336
337 (add => $($t : ty),*) => {
338 $(
339 impl Add<$t> for Number {
340 type Output = Self;
341 fn add(self, other: $t) -> Self {
342 match self {
343 Number::Decimal(f) => (f + other as f64).into(),
344 Number::StandardForm(sf) =>(sf + other).into(),
345 Number::Fraction(fr) => (fr + other).into()
346 }
347 }
348 }
349
350 impl AddAssign<$t> for Number {
351 fn add_assign(&mut self, other: $t) {
352 *self += Number::Decimal(other as f64)
353 }
354 }
355 )*
356 };
357
358 (sub => $($t : ty),*) => {
359 $(
360 impl Sub<$t> for Number {
361 type Output = Self;
362 fn sub(self, other: $t) -> Self {
363 match self {
364 Number::Decimal(f) => Number::Decimal(f - other as f64),
365 Number::StandardForm(sf) => Number::StandardForm(sf - other),
366 Number::Fraction(fr) => (fr - other).into()
367
368 }
369 }
370 }
371
372 impl SubAssign<$t> for Number {
373 fn sub_assign(&mut self, other: $t) {
374 *self -= Number::Decimal(other as f64)
375 }
376 }
377 )*
378 };
379 (mul => $($t : ty),*) => {
380 $(
381 impl Mul<$t> for Number {
382 type Output = Self;
383 fn mul(self, other: $t) -> Self {
384 match self {
385 Number::Decimal(f) => Number::Decimal(f * other as f64),
386 Number::StandardForm(sf) => Number::StandardForm(sf * other),
387 Number::Fraction(fr) => (fr * other).into()
388 }
389 }
390 }
391
392 impl MulAssign<$t> for Number {
393 fn mul_assign(&mut self, other: $t) {
394 *self *= Number::Decimal(other as f64)
395 }
396 }
397 )*
398 };
399 (div => $($t : ty),*) => {
400 $(
401 impl Div<$t> for Number {
402 type Output = Self;
403 fn div(self, other: $t) -> Self {
404 match self {
405 Number::Decimal(f) => Number::Decimal(f / other as f64),
406 Number::StandardForm(sf) => Number::StandardForm(sf / other),
407 Number::Fraction(fr) => (fr / other).into()
408 }
409 }
410 }
411
412 impl DivAssign<$t> for Number {
413 fn div_assign(&mut self, other: $t) {
414 *self /= Number::Decimal(other as f64)
415 }
416 }
417 )*
418 };
419 (rem => $($t : ty),*) => {
420 $(
421 impl Rem<$t> for Number {
422 type Output = Self;
423 fn rem(self, other: $t) -> Self {
424 match self {
425 Number::Decimal(f) => Number::Decimal(f % other as f64),
426 Number::StandardForm(sf) => Number::StandardForm(sf % other),
427 Number::Fraction(fr) => (fr % other).into()
428 }
429 }
430 }
431
432 impl RemAssign<$t> for Number {
433 fn rem_assign(&mut self, other: $t) {
434 *self %= Number::Decimal(other as f64)
435 }
436 }
437 )*
438 };
439 (pow => $($t : ty),*) => {
440 $(
441 #[cfg(feature="num")]
442 impl num_traits::Pow<$t> for StandardForm {
443 type Output = f64;
444
445 #[must_use]
446 fn pow(self, other: $t) -> Self::Output {
447 f64::from(self).powf(other as f64)
448 }
449 }
450 )*
451 };
452 (operations => $($t:ty),*) => {
453 $(
454 primitives!(add => $t);
455 primitives!(sub => $t);
456 primitives!(mul => $t);
457 primitives!(div => $t);
458 primitives!(rem => $t);
459 primitives!(pow => $t);
460 )*
461 }
462}
463
464primitives!(eq => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
465primitives!(ord => u8,u16,u32,u64,i8,i16,i32,i64,f32,f64);
466primitives!(operations => i8, i16, i32, i64, u8, u16, u32, u64,f32,f64);
467
468macro_rules! trig_functions {
469 ($( {
470 $(#[$attr:meta])* $fn : ident
471 })*) => {
472 impl Number {
473 $(
474 $(#[$attr])*
475 pub fn $fn <T : From<f64>>(self) -> T {
476 f64::from(self). $fn ().into()
477 }
478 )*
479
480 }
481 };
482}
483
484trig_functions!(
485 { sin }
487 { cos }
489 { tan }
491 { asin }
493 { acos }
495 { atan }
497 { sinh }
499 { cosh }
501 { tanh }
503 { asinh }
505 { acosh }
507 { atanh }
509);
510
511
512#[cfg(test)]
513mod test {
514 use super::*;
515 #[test]
516 fn test_addition() {
517 let num1 = Number::Decimal(2.5);
518 let num2 = Number::Decimal(3.5);
519 let result = num1 + num2;
520 assert_eq!(result, Number::Decimal(6.0));
521 }
522
523 #[test]
525 fn test_subtraction() {
526 let num1 = Number::Decimal(5.5);
527 let num2 = Number::Decimal(3.5);
528 let result = num1 - num2;
529 assert_eq!(result, Number::Decimal(2.0));
530 }
531
532 #[test]
534 fn test_multiplication() {
535 let num1 = Number::Decimal(2.5);
536 let num2 = Number::Decimal(3.0);
537 let result = num1 * num2;
538 assert_eq!(result, Number::Decimal(7.5));
539 }
540
541 #[test]
543 fn test_division() {
544 let num1 = Number::Decimal(10.0);
545 let num2 = Number::Decimal(2.0);
546 let result = num1 / num2;
547 assert_eq!(result, Number::Decimal(5.0));
548 }
549
550 #[test]
552 fn test_addition_assignment() {
553 let mut num = Number::Decimal(3.0);
554 let num2 = Number::Decimal(2.0);
555 num += num2;
556 assert_eq!(num, Number::Decimal(5.0));
557 }
558
559 #[test]
561 fn test_subtraction_assignment() {
562 let mut num = Number::Decimal(5.0);
563 let num2 = Number::Decimal(3.0);
564 num -= num2;
565 assert_eq!(num, Number::Decimal(2.0));
566 }
567
568 #[test]
570 fn test_multiplication_assignment() {
571 let mut num = Number::Decimal(2.5);
572 let num2 = Number::Decimal(3.0);
573 num *= num2;
574 assert_eq!(num, Number::Decimal(7.5));
575 }
576
577 #[test]
579 fn test_division_assignment() {
580 let mut num = Number::Decimal(10.0);
581 let num2 = Number::Decimal(2.0);
582 num /= num2;
583 assert_eq!(num, Number::Decimal(5.0));
584 }
585
586 #[test]
587 fn test_display_decimal() {
588 let number = Number::Decimal(3.14);
589 assert_eq!(format!("{}", number), "3.14");
590 assert_eq!(number.to_string(), "3.14");
591 }
592
593 #[test]
594 fn test_try_from_valid_number() {
595 let input = "3.14";
597 let result = Number::try_from(input);
598 assert!(result.is_ok());
599
600 if let Ok(Number::Decimal(value)) = result {
602 assert_eq!(value, 3.14);
603 } else {
604 assert!(false, "Expected Ok(Number::Decimal(_)), but got an error.");
605 }
606 }
607
608 #[test]
609 fn test_try_from_invalid_number() {
610 let input = "abc"; let result = Number::try_from(input);
613 assert!(result.is_err());
614
615 if let Err(_) = result {
617 } else {
618 assert!(false, "Expected Err(ParseFloatError), but got a success.");
619 }
620 }
621
622 #[test]
623 fn test_try_from_empty_string() {
624 let input = "";
626 let result = Number::try_from(input);
627 assert!(result.is_err());
628
629 if let Err(_) = result {
631 } else {
632 assert!(false, "Expected Err(ParseFloatError), but got a success.");
633 }
634 }
635}