marwood/
number.rs

1use num::bigint::BigInt;
2use num::traits::FloatConst;
3use num::{
4    BigRational, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Rational64, Signed,
5};
6use num::{Num, Rational32, ToPrimitive};
7use std::cmp::Ordering;
8use std::fmt;
9use std::fmt::{Binary, Formatter, LowerHex, Octal};
10use std::hash::{Hash, Hasher};
11use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub};
12use std::rc::Rc;
13
14/// Exactness
15///
16/// Exactness represents preferred exactness when parsing
17/// a textual representation of a number.
18///
19/// * Exact - Exactness is preferred in cases where the result
20///   would have been inexact. This usually means trying to
21///   convert a float to its rational counterpart.
22///
23/// * Inexact - Inexactness is preferred in cases where
24///   an exact form is given, even if the exact form was an
25///   integer.
26///
27/// * Unspecified - Exactness is not specified. Prefer to
28///   keep inexact values inexact, and exact exact.
29#[derive(Debug)]
30pub enum Exactness {
31    Exact,
32    Inexact,
33    Unspecified,
34}
35
36/// Number
37///
38/// Number implements scheme's numerical tower, converting
39/// between numerical types transparently.
40///
41/// It follows a set of loose rules if possible:
42///
43/// * Exactness if preferred
44/// * Inexactness is infectious
45///
46/// Rationals are provided by the Rational32 type, allowing
47/// for a rational composed of a 32 bit numerator and denominator.
48/// If a rational exceeds these limits, the resulting operation
49/// falls back to "inexact" (float).
50#[derive(Clone, Debug)]
51pub enum Number {
52    Fixnum(i64),
53    Float(f64),
54    BigInt(Rc<BigInt>),
55    Rational(Rational32),
56}
57
58impl Number {
59    pub fn new_bigint<T: Into<BigInt>>(num: T) -> Number {
60        Number::BigInt(Rc::new(num.into()))
61    }
62
63    /// Parse
64    ///
65    /// Parse the text given the desired exactness and radix.
66    pub fn parse_with_exactness(text: &str, exactness: Exactness, radix: u32) -> Option<Number> {
67        match exactness {
68            Exactness::Unspecified => Self::parse(text, radix),
69            Exactness::Exact => Self::parse(text, radix).map(|num| match num.to_exact() {
70                Some(num) => num,
71                None => num,
72            }),
73            Exactness::Inexact => Self::parse(text, radix)
74                .map(|num| num.to_inexact())
75                .map(|it| it.unwrap()),
76        }
77    }
78
79    pub fn parse(text: &str, radix: u32) -> Option<Number> {
80        if let Ok(num) = i64::from_str_radix(text, radix) {
81            Some(Number::from(num))
82        } else if let Ok(num) = BigInt::from_str_radix(text, radix) {
83            Some(Number::from(num))
84        } else if let Some(num) = Self::parse_rational(text, radix) {
85            Some(num)
86        } else if let Ok(num) = f64::from_str_radix(text, radix) {
87            Some(Number::from(num))
88        } else {
89            None
90        }
91    }
92
93    /// Parse Rational
94    ///
95    /// Parse the text according to the given radix. If a 32 bit rational
96    /// cannot be constructed, then attempt to construct a BigRational,
97    /// converting the resulting BigRational into the most appropriate
98    /// Number type.
99    pub fn parse_rational(text: &str, radix: u32) -> Option<Number> {
100        match Rational32::from_str_radix(text, radix) {
101            Ok(num) => {
102                if num.is_integer() {
103                    Some(Number::from(num.to_i64().unwrap()))
104                } else {
105                    Some(num.into())
106                }
107            }
108            Err(_) => match BigRational::from_str_radix(text, radix) {
109                Ok(num) => {
110                    if num.is_integer() {
111                        match num.to_i64() {
112                            Some(num) => Some(num.into()),
113                            None => Some(num.to_integer().into()),
114                        }
115                    } else {
116                        Some(num.to_f64().unwrap_or(f64::NAN).into())
117                    }
118                }
119                Err(_) => None,
120            },
121        }
122    }
123
124    pub fn to_usize(&self) -> Option<usize> {
125        match self {
126            Number::Fixnum(num) if *num >= 0 => num.to_usize(),
127            Number::BigInt(num)
128                if **num >= BigInt::from(0) && **num <= BigInt::from(usize::MAX) =>
129            {
130                Some(num.to_usize().unwrap())
131            }
132            Number::Rational(num) if num.is_integer() => num.to_usize(),
133            _ => None,
134        }
135    }
136
137    pub fn to_i64(&self) -> Option<i64> {
138        match self {
139            Number::Fixnum(num) => Some(*num),
140            Number::BigInt(num) => num.to_i64(),
141            Number::Rational(num) if num.is_integer() => num.to_i64(),
142            Number::Float(num) if self.is_integer() => num.to_i64(),
143            _ => None,
144        }
145    }
146
147    pub fn to_u64(&self) -> Option<u64> {
148        match self {
149            Number::Fixnum(num) if *num >= 0 => Some(*num as u64),
150            Number::BigInt(num) if **num >= BigInt::from(0) && **num <= BigInt::from(u64::MAX) => {
151                Some(num.to_u64().unwrap())
152            }
153            Number::Rational(num) if num.is_integer() => num.to_u64(),
154            Number::Float(num) if self.is_integer() => num.to_u64(),
155            _ => None,
156        }
157    }
158
159    pub fn to_u32(&self) -> Option<u32> {
160        match self {
161            Number::Fixnum(num) => num.to_u32(),
162            Number::BigInt(num) if **num >= BigInt::from(0) && **num <= BigInt::from(u32::MAX) => {
163                Some(num.to_u32().unwrap())
164            }
165            Number::Rational(num) if num.is_integer() => num.to_u32(),
166            Number::Float(num) if self.is_integer() => num.to_u32(),
167            _ => None,
168        }
169    }
170
171    pub fn to_f64(&self) -> Option<f64> {
172        match self {
173            Number::Fixnum(num) => num.to_f64(),
174            Number::BigInt(num) => num.to_f64(),
175            Number::Rational(num) => num.to_f64(),
176            Number::Float(num) => Some(*num),
177        }
178    }
179
180    pub fn is_integer(&self) -> bool {
181        match self {
182            Number::Fixnum(_) => true,
183            Number::Float(num) => num.floor() == *num,
184            Number::BigInt(_) => true,
185            Number::Rational(num) => num.is_integer(),
186        }
187    }
188
189    pub fn is_complex(&self) -> bool {
190        true
191    }
192
193    pub fn is_real(&self) -> bool {
194        true
195    }
196
197    pub fn is_rational(&self) -> bool {
198        match self {
199            Number::Fixnum(_) => true,
200            Number::Float(_) => false,
201            Number::BigInt(_) => true,
202            Number::Rational(_) => true,
203        }
204    }
205
206    pub fn is_zero(&self) -> bool {
207        self == &Number::from(0)
208    }
209
210    pub fn to_inexact(&self) -> Option<Number> {
211        match self {
212            Number::Fixnum(num) => Some((*num as f64).into()),
213            Number::Float(num) => Some((*num).into()),
214            Number::BigInt(num) => Some(num.to_f64().unwrap().into()),
215            Number::Rational(num) => Some(num.to_f64().unwrap().into()),
216        }
217    }
218
219    pub fn to_exact(&self) -> Option<Number> {
220        match self {
221            Number::Float(num) => {
222                if self.is_integer() {
223                    match num.to_i64() {
224                        Some(integer) => Some(Number::Fixnum(integer)),
225                        None => num.to_i128().map(|num| BigInt::from(num).into()),
226                    }
227                } else {
228                    match Rational32::from_f64(*num) {
229                        Some(num) => Some(num.into()),
230                        None => Some((*num).into()),
231                    }
232                }
233            }
234            Number::BigInt(_) | Number::Rational(_) | Number::Fixnum(_) => Some(self.clone()),
235        }
236    }
237
238    pub fn numerator(&self) -> Number {
239        match self {
240            Number::Fixnum(_) => self.clone(),
241            Number::Float(num) => match BigRational::from_f64(*num) {
242                Some(rational) => Number::from(rational.numer().clone()),
243                None => self.clone(),
244            },
245            Number::BigInt(_) => self.clone(),
246            Number::Rational(num) => (*num.numer() as i64).into(),
247        }
248    }
249
250    pub fn denominator(&self) -> Number {
251        match self {
252            Number::Fixnum(_) => 1.into(),
253            Number::Float(num) => match BigRational::from_f64(*num) {
254                Some(rational) => Number::from(rational.denom().clone()),
255                None => self.clone(),
256            },
257            Number::BigInt(_) => 1.into(),
258            Number::Rational(num) => (*num.denom() as i64).into(),
259        }
260    }
261
262    pub fn abs(&self) -> Number {
263        match self {
264            Number::Fixnum(num) => num.unsigned_abs().into(),
265            Number::Float(num) => num.abs().into(),
266            Number::BigInt(num) => num.abs().into(),
267            Number::Rational(num) => num.abs().into(),
268        }
269    }
270
271    pub fn modulo(&self, rhs: &Number) -> Option<Number> {
272        match self % rhs {
273            Some(num) => &(&num + rhs) % rhs,
274            None => None,
275        }
276    }
277
278    pub fn round(&self) -> Number {
279        match self {
280            Number::Fixnum(_) => self.clone(),
281            Number::Float(num) => num.round().into(),
282            Number::BigInt(_) => self.clone(),
283            Number::Rational(num) => num.round().into(),
284        }
285    }
286
287    pub fn floor(&self) -> Number {
288        match self {
289            Number::Fixnum(_) => self.clone(),
290            Number::Float(num) => num.floor().into(),
291            Number::BigInt(_) => self.clone(),
292            Number::Rational(num) => num.floor().into(),
293        }
294    }
295
296    pub fn ceil(&self) -> Number {
297        match self {
298            Number::Fixnum(_) => self.clone(),
299            Number::Float(num) => num.ceil().into(),
300            Number::BigInt(_) => self.clone(),
301            Number::Rational(num) => num.ceil().into(),
302        }
303    }
304
305    pub fn truncate(&self) -> Number {
306        match self {
307            Number::Fixnum(_) => self.clone(),
308            Number::Float(num) => num.trunc().into(),
309            Number::BigInt(_) => self.clone(),
310            Number::Rational(num) => num.trunc().into(),
311        }
312    }
313
314    pub fn pow(&self, exp: u32) -> Number {
315        match self {
316            Number::Fixnum(num) => match num.checked_pow(exp) {
317                Some(num) => num.into(),
318                None => BigInt::from(*num).pow(exp).into(),
319            },
320            Number::Float(num) => num.powf(exp as f64).into(),
321            Number::BigInt(lhs) => lhs.pow(exp).into(),
322            Number::Rational(num) => {
323                if exp.to_i32().is_some() {
324                    num.pow(exp as i32).into()
325                } else {
326                    num.to_f64().unwrap_or(f64::NAN).powf(exp as f64).into()
327                }
328            }
329        }
330    }
331}
332
333impl Eq for Number {}
334impl PartialEq for Number {
335    fn eq(&self, rhs: &Self) -> bool {
336        match self {
337            Number::Fixnum(lhs) => match rhs {
338                Number::Fixnum(rhs) => lhs == rhs,
339                Number::BigInt(rhs) => BigInt::from(*lhs) == **rhs,
340                Number::Float(rhs) => *lhs as f64 == *rhs,
341                Number::Rational(rhs) => {
342                    if lhs.to_i32().is_some() {
343                        Rational32::from_integer(*lhs as i32) == *rhs
344                    } else {
345                        false
346                    }
347                }
348            },
349            Number::BigInt(lhs) => match rhs {
350                Number::Fixnum(rhs) => **lhs == BigInt::from(*rhs),
351                Number::BigInt(rhs) => lhs == rhs,
352                Number::Float(rhs) => lhs.to_f64().unwrap() == *rhs,
353                Number::Rational(rhs) => match lhs.to_i32() {
354                    Some(lhs) => Rational32::from_integer(lhs) == *rhs,
355                    None => false,
356                },
357            },
358            Number::Float(lhs) => match rhs {
359                Number::Fixnum(rhs) => *lhs == *rhs as f64,
360                Number::Float(rhs) => lhs == rhs,
361                Number::BigInt(rhs) => *lhs == rhs.to_f64().unwrap(),
362                Number::Rational(rhs) => match rhs.to_f64() {
363                    Some(rhs) => *lhs == rhs,
364                    None => false,
365                },
366            },
367            Number::Rational(lhs) => match rhs {
368                Number::Fixnum(rhs) => {
369                    if rhs.to_i32().is_some() {
370                        Rational32::from_integer(*rhs as i32) == *lhs
371                    } else {
372                        false
373                    }
374                }
375                Number::Float(rhs) => match lhs.to_f64() {
376                    Some(lhs) => lhs == *rhs,
377                    None => false,
378                },
379                Number::BigInt(rhs) => match rhs.to_i32() {
380                    Some(rhs) => *lhs == Rational32::from_integer(rhs),
381                    None => false,
382                },
383                Number::Rational(rhs) => lhs == rhs,
384            },
385        }
386    }
387}
388
389impl PartialOrd for Number {
390    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
391        match self {
392            Number::Fixnum(lhs) => match rhs {
393                Number::Fixnum(rhs) => lhs.partial_cmp(rhs),
394                Number::BigInt(rhs) => BigInt::from(*lhs).partial_cmp(&**rhs),
395                Number::Float(rhs) => (*lhs as f64).partial_cmp(rhs),
396                Number::Rational(rhs) => {
397                    if lhs.to_i32().is_some() {
398                        Rational32::from_integer(*lhs as i32).partial_cmp(rhs)
399                    } else {
400                        Some(Ordering::Greater)
401                    }
402                }
403            },
404            Number::BigInt(lhs) => match rhs {
405                Number::Fixnum(rhs) => (**lhs).partial_cmp(&BigInt::from(*rhs)),
406                Number::BigInt(rhs) => (**lhs).partial_cmp(&**rhs),
407                Number::Float(rhs) => (**lhs).to_f64().unwrap().partial_cmp(rhs),
408                Number::Rational(rhs) => match lhs.to_i32() {
409                    Some(lhs) => Rational32::from_integer(lhs).partial_cmp(rhs),
410                    None => Some(Ordering::Greater),
411                },
412            },
413            Number::Float(lhs) => match rhs {
414                Number::Fixnum(rhs) => lhs.partial_cmp(&(*rhs as f64)),
415                Number::Float(rhs) => lhs.partial_cmp(rhs),
416                Number::BigInt(rhs) => lhs.partial_cmp(&(**rhs).to_f64().unwrap()),
417                Number::Rational(rhs) => lhs.partial_cmp(&rhs.to_f64().unwrap()),
418            },
419            Number::Rational(lhs) => match rhs {
420                Number::Fixnum(rhs) => {
421                    if rhs.to_i32().is_some() {
422                        lhs.partial_cmp(&Rational32::from_integer(*rhs as i32))
423                    } else {
424                        Some(Ordering::Less)
425                    }
426                }
427                Number::Float(rhs) => lhs.to_f64().unwrap().partial_cmp(rhs),
428                Number::BigInt(rhs) => match rhs.to_i32() {
429                    Some(rhs) => lhs.partial_cmp(&Rational32::from_integer(rhs)),
430                    None => Some(Ordering::Less),
431                },
432                Number::Rational(rhs) => lhs.partial_cmp(rhs),
433            },
434        }
435    }
436}
437
438impl AddAssign for Number {
439    fn add_assign(&mut self, rhs: Self) {
440        let result = &*self + &rhs;
441        *self = result;
442    }
443}
444
445impl MulAssign for Number {
446    fn mul_assign(&mut self, rhs: Self) {
447        let result = &*self * &rhs;
448        *self = result;
449    }
450}
451
452impl DivAssign for Number {
453    fn div_assign(&mut self, rhs: Self) {
454        let result = &*self / &rhs;
455        *self = result;
456    }
457}
458
459impl Add for Number {
460    type Output = Number;
461    fn add(self, rhs: Self) -> Self::Output {
462        (&self).add(&rhs)
463    }
464}
465
466impl Add for &Number {
467    type Output = Number;
468
469    fn add(self, rhs: Self) -> Self::Output {
470        match self {
471            Number::Fixnum(lhs) => match rhs {
472                Number::Fixnum(rhs) => match lhs.checked_add(rhs) {
473                    Some(num) => Number::Fixnum(num),
474                    None => (BigInt::from(*lhs) + rhs).into(),
475                },
476                Number::BigInt(rhs) => (&**rhs + lhs).into(),
477                Number::Float(rhs) => (*lhs as f64 + rhs).into(),
478                Number::Rational(rhs) => {
479                    if lhs.to_i32().is_some() {
480                        let lhs_rational = Rational32::from_integer(*lhs as i32);
481                        match lhs_rational.checked_add(rhs) {
482                            Some(num) => num.into(),
483                            None => (*lhs as f64 + rhs.to_f64().unwrap_or(f64::NAN)).into(),
484                        }
485                    } else {
486                        (*lhs as f64 + rhs.to_f64().unwrap_or(f64::NAN)).into()
487                    }
488                }
489            },
490            Number::BigInt(lhs) => match rhs {
491                Number::Fixnum(rhs) => (&**lhs + rhs).into(),
492                Number::BigInt(rhs) => (&**lhs + &**rhs).into(),
493                Number::Float(rhs) => (lhs.to_f64().unwrap() + *rhs).into(),
494                Number::Rational(rhs) => {
495                    if rhs.is_integer() {
496                        (&**lhs + rhs.to_integer()).into()
497                    } else {
498                        (lhs.to_f64().unwrap() + rhs.to_f64().unwrap_or(f64::NAN)).into()
499                    }
500                }
501            },
502            Number::Float(lhs) => match rhs {
503                Number::Fixnum(rhs) => (*lhs + *rhs as f64).into(),
504                Number::Float(rhs) => (*lhs + *rhs).into(),
505                Number::BigInt(rhs) => (*lhs + rhs.to_f64().unwrap()).into(),
506                Number::Rational(rhs) => (*lhs + rhs.to_f64().unwrap_or(f64::NAN)).into(),
507            },
508            Number::Rational(lhs) => match rhs {
509                Number::Fixnum(rhs) => {
510                    if rhs.to_i32().is_some() {
511                        let rhs_rational = Rational32::from_integer(*rhs as i32);
512                        match rhs_rational.checked_add(lhs) {
513                            Some(num) => num.into(),
514                            None => (lhs.to_f64().unwrap_or(f64::NAN) + *rhs as f64).into(),
515                        }
516                    } else {
517                        (lhs.to_f64().unwrap_or(f64::NAN) + *rhs as f64).into()
518                    }
519                }
520                Number::Float(rhs) => (lhs.to_f64().unwrap_or(f64::NAN) + *rhs).into(),
521                Number::BigInt(rhs) => {
522                    if lhs.is_integer() {
523                        (&**rhs + lhs.to_integer()).into()
524                    } else {
525                        (rhs.to_f64().unwrap() + lhs.to_f64().unwrap_or(f64::NAN)).into()
526                    }
527                }
528                Number::Rational(rhs) => match lhs.checked_add(rhs) {
529                    Some(num) => num.into(),
530                    None => {
531                        (lhs.to_f64().unwrap_or(f64::NAN) + rhs.to_f64().unwrap_or(f64::NAN)).into()
532                    }
533                },
534            },
535        }
536    }
537}
538
539impl Mul for Number {
540    type Output = Number;
541    fn mul(self, rhs: Self) -> Self::Output {
542        (&self).mul(&rhs)
543    }
544}
545
546impl Mul for &Number {
547    type Output = Number;
548
549    fn mul(self, rhs: Self) -> Self::Output {
550        match self {
551            Number::Fixnum(lhs) => match rhs {
552                Number::Fixnum(rhs) => match lhs.checked_mul(rhs) {
553                    Some(num) => Number::Fixnum(num),
554                    None => (BigInt::from(*lhs) * rhs).into(),
555                },
556                Number::BigInt(rhs) => (&**rhs * lhs).into(),
557                Number::Float(rhs) => (*lhs as f64 * rhs).into(),
558                Number::Rational(rhs) => {
559                    if lhs.to_i32().is_some() {
560                        let lhs_rational = Rational32::from_integer(*lhs as i32);
561                        match lhs_rational.checked_mul(rhs) {
562                            Some(num) => num.into(),
563                            None => (*lhs as f64 * rhs.to_f64().unwrap_or(f64::NAN)).into(),
564                        }
565                    } else {
566                        (*lhs as f64 * rhs.to_f64().unwrap_or(f64::NAN)).into()
567                    }
568                }
569            },
570            Number::BigInt(lhs) => match rhs {
571                Number::Fixnum(rhs) => (&**lhs * rhs).into(),
572                Number::BigInt(rhs) => (&**lhs * &**rhs).into(),
573                Number::Float(rhs) => (lhs.to_f64().unwrap() * *rhs).into(),
574                Number::Rational(rhs) => {
575                    if rhs.is_integer() {
576                        (&**lhs * rhs.to_integer()).into()
577                    } else {
578                        (lhs.to_f64().unwrap() * rhs.to_f64().unwrap_or(f64::NAN)).into()
579                    }
580                }
581            },
582            Number::Float(lhs) => match rhs {
583                Number::Fixnum(rhs) => (*lhs * *rhs as f64).into(),
584                Number::Float(rhs) => (*lhs * *rhs).into(),
585                Number::BigInt(rhs) => (*lhs * rhs.to_f64().unwrap()).into(),
586                Number::Rational(rhs) => (*lhs * rhs.to_f64().unwrap_or(f64::NAN)).into(),
587            },
588            Number::Rational(lhs) => match rhs {
589                Number::Fixnum(rhs) => {
590                    if rhs.to_i32().is_some() {
591                        let rhs_rational = Rational32::from_integer(*rhs as i32);
592                        match rhs_rational.checked_mul(lhs) {
593                            Some(num) => num.into(),
594                            None => (lhs.to_f64().unwrap_or(f64::NAN) * *rhs as f64).into(),
595                        }
596                    } else {
597                        (lhs.to_f64().unwrap_or(f64::NAN) * *rhs as f64).into()
598                    }
599                }
600                Number::Float(rhs) => (lhs.to_f64().unwrap_or(f64::NAN) * *rhs).into(),
601                Number::BigInt(rhs) => {
602                    if lhs.is_integer() {
603                        (&**rhs * lhs.to_integer()).into()
604                    } else {
605                        (rhs.to_f64().unwrap() * lhs.to_f64().unwrap_or(f64::NAN)).into()
606                    }
607                }
608                Number::Rational(rhs) => match lhs.checked_mul(rhs) {
609                    Some(num) => num.into(),
610                    None => {
611                        (lhs.to_f64().unwrap_or(f64::NAN) * rhs.to_f64().unwrap_or(f64::NAN)).into()
612                    }
613                },
614            },
615        }
616    }
617}
618
619impl Sub for Number {
620    type Output = Number;
621    fn sub(self, rhs: Self) -> Self::Output {
622        (&self).sub(&rhs)
623    }
624}
625
626impl Sub for &Number {
627    type Output = Number;
628
629    fn sub(self, rhs: Self) -> Self::Output {
630        match self {
631            Number::Fixnum(lhs) => match rhs {
632                Number::Fixnum(rhs) => match lhs.checked_sub(rhs) {
633                    Some(num) => Number::Fixnum(num),
634                    None => (BigInt::from(*lhs) - rhs).into(),
635                },
636                Number::BigInt(rhs) => (lhs - &**rhs).into(),
637                Number::Float(rhs) => (*lhs as f64 - rhs).into(),
638                Number::Rational(rhs) => {
639                    if lhs.to_i32().is_some() {
640                        let lhs_rational = Rational32::from_integer(*lhs as i32);
641                        match lhs_rational.checked_sub(rhs) {
642                            Some(num) => num.into(),
643                            None => (*lhs as f64 - rhs.to_f64().unwrap_or(f64::NAN)).into(),
644                        }
645                    } else {
646                        (*lhs as f64 - rhs.to_f64().unwrap_or(f64::NAN)).into()
647                    }
648                }
649            },
650            Number::BigInt(lhs) => match rhs {
651                Number::Fixnum(rhs) => (&**lhs - rhs).into(),
652                Number::BigInt(rhs) => (&**lhs - &**rhs).into(),
653                Number::Float(rhs) => (lhs.to_f64().unwrap() - *rhs).into(),
654                Number::Rational(rhs) => {
655                    if rhs.is_integer() {
656                        (&**lhs - rhs.to_integer()).into()
657                    } else {
658                        (lhs.to_f64().unwrap() - rhs.to_f64().unwrap_or(f64::NAN)).into()
659                    }
660                }
661            },
662            Number::Float(lhs) => match rhs {
663                Number::Fixnum(rhs) => (*lhs - *rhs as f64).into(),
664                Number::Float(rhs) => (*lhs - *rhs).into(),
665                Number::BigInt(rhs) => (*lhs - rhs.to_f64().unwrap()).into(),
666                Number::Rational(rhs) => (*lhs - rhs.to_f64().unwrap_or(f64::NAN)).into(),
667            },
668            Number::Rational(lhs) => match rhs {
669                Number::Fixnum(rhs) => {
670                    if rhs.to_i32().is_some() {
671                        let rhs_rational = Rational32::from_integer(*rhs as i32);
672                        match lhs.checked_sub(&rhs_rational) {
673                            Some(num) => num.into(),
674                            None => (lhs.to_f64().unwrap_or(f64::NAN) - *rhs as f64).into(),
675                        }
676                    } else {
677                        (lhs.to_f64().unwrap_or(f64::NAN) - *rhs as f64).into()
678                    }
679                }
680                Number::Float(rhs) => (lhs.to_f64().unwrap_or(f64::NAN) - *rhs).into(),
681                Number::BigInt(rhs) => {
682                    if lhs.is_integer() {
683                        (BigInt::from(lhs.to_integer()) - &**rhs).into()
684                    } else {
685                        (lhs.to_f64().unwrap_or(f64::NAN) - rhs.to_f64().unwrap()).into()
686                    }
687                }
688                Number::Rational(rhs) => match lhs.checked_sub(rhs) {
689                    Some(num) => num.into(),
690                    None => {
691                        (lhs.to_f64().unwrap_or(f64::NAN) - rhs.to_f64().unwrap_or(f64::NAN)).into()
692                    }
693                },
694            },
695        }
696    }
697}
698
699impl Div for Number {
700    type Output = Number;
701    fn div(self, rhs: Self) -> Self::Output {
702        (&self).div(&rhs)
703    }
704}
705
706impl Div for &Number {
707    type Output = Number;
708
709    fn div(self, rhs: Self) -> Self::Output {
710        match self {
711            Number::Fixnum(lhs) => match rhs {
712                Number::Fixnum(rhs) => {
713                    if lhs.to_i32().is_some() && rhs.to_i32().is_some() {
714                        Rational32::new(*lhs as i32, *rhs as i32).into()
715                    } else {
716                        (*lhs as f64 / *rhs as f64).into()
717                    }
718                }
719                Number::BigInt(rhs) => {
720                    if lhs.to_i32().is_some() && rhs.to_i32().is_some() {
721                        Rational32::new(*lhs as i32, rhs.to_i32().unwrap()).into()
722                    } else {
723                        (*lhs as f64 / rhs.to_f64().unwrap_or(f64::NAN)).into()
724                    }
725                }
726                Number::Float(rhs) => (*lhs as f64 / rhs).into(),
727                Number::Rational(rhs) => {
728                    if lhs.to_i32().is_some() {
729                        match Rational32::from_integer(*lhs as i32).checked_div(rhs) {
730                            Some(num) => num.into(),
731                            None => (*lhs as f64 / rhs.to_f64().unwrap_or(f64::NAN)).into(),
732                        }
733                    } else {
734                        (*lhs as f64 / rhs.to_f64().unwrap_or(f64::NAN)).into()
735                    }
736                }
737            },
738            Number::BigInt(lhs) => match rhs {
739                Number::Fixnum(rhs) => {
740                    if lhs.to_i32().is_some() && rhs.to_i32().is_some() {
741                        (Rational32::new(lhs.to_i32().unwrap(), *rhs as i32)).into()
742                    } else {
743                        (lhs.to_f64().unwrap_or(f64::NAN) / *rhs as f64).into()
744                    }
745                }
746                Number::BigInt(rhs) => {
747                    if lhs.to_i32().is_some() && rhs.to_i32().is_some() {
748                        (Rational32::new(lhs.to_i32().unwrap(), rhs.to_i32().unwrap())).into()
749                    } else {
750                        (lhs.to_f64().unwrap_or(f64::NAN) / rhs.to_f64().unwrap_or(f64::NAN)).into()
751                    }
752                }
753                Number::Float(rhs) => (lhs.to_f64().unwrap() / *rhs).into(),
754                Number::Rational(rhs) => {
755                    if lhs.to_i32().is_some() {
756                        match Rational32::from_integer(lhs.to_i32().unwrap()).checked_div(rhs) {
757                            Some(num) => num.into(),
758                            None => {
759                                (lhs.to_f64().unwrap() / rhs.to_f64().unwrap_or(f64::NAN)).into()
760                            }
761                        }
762                    } else {
763                        (lhs.to_f64().unwrap() / rhs.to_f64().unwrap_or(f64::NAN)).into()
764                    }
765                }
766            },
767            Number::Float(lhs) => match rhs {
768                Number::Fixnum(rhs) => (*lhs / *rhs as f64).into(),
769                Number::Float(rhs) => (*lhs / *rhs).into(),
770                Number::BigInt(rhs) => (*lhs / rhs.to_f64().unwrap()).into(),
771                Number::Rational(rhs) => (lhs / rhs.to_f64().unwrap_or(f64::NAN)).into(),
772            },
773            Number::Rational(lhs) => match rhs {
774                Number::Fixnum(rhs) => {
775                    if rhs.to_i32().is_some() {
776                        match lhs.checked_div(&Rational32::from_integer(*rhs as i32)) {
777                            Some(num) => num.into(),
778                            None => (lhs.to_f64().unwrap_or(f64::MAX) / *rhs as f64).into(),
779                        }
780                    } else {
781                        (lhs.to_f64().unwrap_or(f64::MAX) / *rhs as f64).into()
782                    }
783                }
784                Number::Float(rhs) => (lhs.to_f64().unwrap_or(f64::NAN) / *rhs).into(),
785                Number::BigInt(rhs) => {
786                    if rhs.to_i32().is_some() {
787                        match lhs.checked_div(&Rational32::from_integer(rhs.to_i32().unwrap())) {
788                            Some(num) => num.into(),
789                            None => {
790                                (lhs.to_f64().unwrap_or(f64::MAX) / rhs.to_f64().unwrap()).into()
791                            }
792                        }
793                    } else {
794                        (lhs.to_f64().unwrap_or(f64::MAX) / rhs.to_f64().unwrap()).into()
795                    }
796                }
797                Number::Rational(rhs) => match lhs.checked_div(rhs) {
798                    Some(num) => num.into(),
799                    None => {
800                        (lhs.to_f64().unwrap_or(f64::NAN) / rhs.to_f64().unwrap_or(f64::NAN)).into()
801                    }
802                },
803            },
804        }
805    }
806}
807
808impl Number {
809    /// Quotient with truncation (rounding towards zero).
810    ///
811    /// The spec only defines this function for integer inputs. Since that includes integral floats,
812    /// we define quotient over all floats with the expectation that the caller can check the
813    /// inputs for strict conformance.
814    pub fn quotient(&self, rhs: &Self) -> Option<Number> {
815        match self {
816            Number::Fixnum(lhs) => match rhs {
817                Number::Fixnum(rhs) => Some((lhs / rhs).into()),
818                Number::BigInt(rhs) => Some((BigInt::from(*lhs) / &**rhs).into()),
819                Number::Float(rhs) => lhs.to_f64().map(|lhs| (lhs as f64 / rhs).trunc().into()),
820                Number::Rational(rhs) => {
821                    if rhs.is_integer() {
822                        Some((*lhs / rhs.to_i64().unwrap()).into())
823                    } else {
824                        None
825                    }
826                }
827            },
828            Number::BigInt(lhs) => match rhs {
829                Number::Fixnum(rhs) => Some((&**lhs / rhs).into()),
830                Number::BigInt(rhs) => Some((&**lhs / &**rhs).into()),
831                Number::Float(rhs) => lhs.to_f64().map(|lhs| (lhs / rhs).trunc().into()),
832                Number::Rational(rhs) => {
833                    if rhs.is_integer() {
834                        Some((&**lhs / BigInt::from(rhs.to_i32().unwrap())).into())
835                    } else {
836                        None
837                    }
838                }
839            },
840            Number::Float(lhs) => match rhs {
841                Number::Fixnum(rhs) => Some((lhs / *rhs as f64).into()),
842                Number::Float(rhs) => Some((lhs / rhs).trunc().into()),
843                Number::BigInt(_) => None,
844                Number::Rational(rhs) => rhs.to_f64().map(|rhs| (lhs / rhs).into()),
845            },
846            Number::Rational(lhs) if lhs.is_integer() => match rhs {
847                Number::Fixnum(rhs) => Some((lhs.to_i64().unwrap() / *rhs).into()),
848                Number::Float(rhs) => lhs.to_f64().map(|lhs| (lhs / rhs).trunc().into()),
849                Number::BigInt(rhs) => Some((BigInt::from(lhs.to_i64().unwrap()) / &**rhs).into()),
850                Number::Rational(rhs) => {
851                    if rhs.is_integer() {
852                        Some((lhs / rhs).into())
853                    } else {
854                        None
855                    }
856                }
857            },
858            Number::Rational(_) => None,
859        }
860    }
861}
862
863impl Rem for Number {
864    type Output = Option<Number>;
865    fn rem(self, rhs: Self) -> Self::Output {
866        (&self).rem(&rhs)
867    }
868}
869
870impl Rem for &Number {
871    type Output = Option<Number>;
872
873    /// Remainder
874    ///
875    /// The spec only defines remainder for integers but this operation is also used by other
876    /// functions that deal with numbers of all types internally.
877    fn rem(self, rhs: Self) -> Self::Output {
878        match self {
879            Number::Fixnum(lhs) => match rhs {
880                Number::Fixnum(rhs) => Some((lhs % rhs).into()),
881                Number::BigInt(rhs) => Some((BigInt::from(*lhs) % &**rhs).into()),
882                Number::Float(rhs) => Some((*lhs as f64 % rhs).into()),
883                Number::Rational(rhs) => {
884                    let result = Rational64::from_integer(*lhs)
885                        % Rational64::from((*rhs.numer() as i64, *rhs.denom() as i64));
886                    // lhs % rhs is guaranteed to be less than rhs. Since lhs is a whole integer,
887                    // both numerator and denominator still fit in an i32.
888                    Some(Rational32::from((*result.numer() as i32, *result.denom() as i32)).into())
889                }
890            },
891            Number::BigInt(lhs) => match rhs {
892                Number::Fixnum(rhs) => Some((&**lhs % rhs).into()),
893                Number::BigInt(rhs) => Some((&**lhs % &**rhs).into()),
894                Number::Float(_) => None,
895                Number::Rational(rhs) => {
896                    if rhs.is_integer() {
897                        // fast path if rhs is an integer
898                        Some((&**lhs % BigInt::from(rhs.to_i32().unwrap())).into())
899                    } else {
900                        // if rhs is a rational, we can mod the bigint by the numerator
901                        // and then divide the result by the denominator.
902                        // Exercise to the reader: Prove that X % N/M == (X % N) / M
903                        let denom = rhs.denom();
904                        let numer_mod =
905                            (&**lhs * BigInt::from(*denom)) % BigInt::from(*rhs.numer());
906                        Some(Rational32::new(numer_mod.to_i32().unwrap(), *denom).into())
907                    }
908                }
909            },
910            Number::Float(lhs) => match rhs {
911                Number::Fixnum(rhs) => Some((lhs % *rhs as f64).into()),
912                Number::Float(rhs) => Some((lhs % rhs).into()),
913                // BigInt::to_f64 converts to infinity if it is too large
914                // which yields the correct result since a % b = a if a < b
915                Number::BigInt(rhs) => rhs.to_f64().map(|rhs| (lhs % rhs).into()),
916                Number::Rational(rhs) => rhs.to_f64().map(|rhs| (lhs % rhs).into()),
917            },
918            Number::Rational(lhs) => match rhs {
919                Number::Fixnum(rhs) => Some((lhs.to_i64().unwrap() % *rhs).into()),
920                Number::Float(rhs) => lhs.to_f64().map(|lhs| (lhs % rhs).into()),
921                Number::BigInt(rhs) => Some((BigInt::from(lhs.to_i64().unwrap()) % &**rhs).into()),
922                Number::Rational(rhs) => Some((lhs % rhs).into()),
923            },
924        }
925    }
926}
927
928impl Hash for Number {
929    fn hash<H: Hasher>(&self, state: &mut H) {
930        match self {
931            Number::Fixnum(num) => num.hash(state),
932            Number::Float(_) => panic!("unexpected hash of f64"),
933            Number::BigInt(num) => num.hash(state),
934            Number::Rational(num) => num.hash(state),
935        }
936    }
937}
938
939impl fmt::Display for Number {
940    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
941        match self {
942            Number::Fixnum(num) => write!(f, "{}", num),
943            Number::BigInt(num) => write!(f, "{}", num),
944            Number::Float(num) if *num > 1E10 => write!(f, "{:e}", num),
945            Number::Float(num) if self.is_integer() => write!(f, "{:.1}", num),
946            Number::Float(num) => write!(f, "{}", num),
947            Number::Rational(num) => write!(f, "{}", num),
948        }
949    }
950}
951
952fn write_float_fract(mut num: f64, radix: usize, f: &mut Formatter<'_>) -> fmt::Result {
953    let mut first_digit = true;
954    loop {
955        num = num.fract() * radix as f64;
956        if num == 0_f64 {
957            break;
958        }
959        if first_digit {
960            write!(f, ".{:x}", num.trunc().abs() as i64)?;
961            first_digit = false;
962        } else {
963            write!(f, "{:x}", num.trunc().abs() as i64)?;
964        }
965    }
966    Ok(())
967}
968
969impl LowerHex for Number {
970    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
971        match self {
972            Number::Fixnum(num) => fmt::LowerHex::fmt(num, f),
973            Number::Float(num) => {
974                if *num < 0_f64 {
975                    write!(f, "-")?;
976                }
977                write!(f, "{:x}", num.trunc().abs() as i64)?;
978                write_float_fract(*num, 16, f)
979            }
980            Number::BigInt(num) => fmt::LowerHex::fmt(num.as_ref(), f),
981            Number::Rational(num) => fmt::LowerHex::fmt(num, f),
982        }
983    }
984}
985
986impl Octal for Number {
987    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
988        match self {
989            Number::Fixnum(num) => fmt::Octal::fmt(num, f),
990            Number::Float(num) => {
991                if *num < 0_f64 {
992                    write!(f, "-")?;
993                }
994                write!(f, "{:o}", num.trunc().abs() as i64)?;
995                write_float_fract(*num, 8, f)
996            }
997            Number::BigInt(num) => fmt::Octal::fmt(num.as_ref(), f),
998            Number::Rational(num) => fmt::Octal::fmt(num, f),
999        }
1000    }
1001}
1002
1003impl Binary for Number {
1004    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1005        match self {
1006            Number::Fixnum(num) => fmt::Binary::fmt(num, f),
1007            Number::Float(num) => {
1008                if *num < 0_f64 {
1009                    write!(f, "-")?;
1010                }
1011                write!(f, "{:b}", num.trunc().abs() as i64)?;
1012                write_float_fract(*num, 2, f)
1013            }
1014            Number::BigInt(num) => fmt::Binary::fmt(num.as_ref(), f),
1015            Number::Rational(num) => fmt::Binary::fmt(num, f),
1016        }
1017    }
1018}
1019
1020impl From<u32> for Number {
1021    fn from(num: u32) -> Self {
1022        Number::Fixnum(num as i64)
1023    }
1024}
1025
1026impl From<i32> for Number {
1027    fn from(num: i32) -> Self {
1028        Number::Fixnum(num as i64)
1029    }
1030}
1031
1032impl From<u64> for Number {
1033    fn from(num: u64) -> Self {
1034        if num > i64::MAX as u64 {
1035            Number::new_bigint(BigInt::from(num))
1036        } else {
1037            Number::Fixnum(num as i64)
1038        }
1039    }
1040}
1041
1042impl From<usize> for Number {
1043    fn from(num: usize) -> Self {
1044        if num > i64::MAX as usize {
1045            Number::new_bigint(BigInt::from(num))
1046        } else {
1047            Number::Fixnum(num as i64)
1048        }
1049    }
1050}
1051
1052impl From<i64> for Number {
1053    fn from(num: i64) -> Self {
1054        Number::Fixnum(num)
1055    }
1056}
1057
1058impl From<f64> for Number {
1059    fn from(num: f64) -> Self {
1060        Number::Float(num)
1061    }
1062}
1063
1064impl From<BigInt> for Number {
1065    fn from(num: BigInt) -> Self {
1066        Number::BigInt(Rc::new(num))
1067    }
1068}
1069
1070impl From<Rational32> for Number {
1071    fn from(num: Rational32) -> Self {
1072        Number::Rational(num)
1073    }
1074}
1075
1076/// Trigonometric functions
1077impl Number {
1078    pub fn exp(&self) -> Option<Number> {
1079        match self {
1080            Number::Fixnum(num) => num.to_f64().map(|num| num.exp().into()),
1081            Number::Float(num) => Some(num.exp().into()),
1082            Number::BigInt(num) => num.to_f64().map(|num| num.exp().into()),
1083            Number::Rational(num) => num.to_f64().map(|num| num.exp().into()),
1084        }
1085    }
1086
1087    pub fn log(&self) -> Option<Number> {
1088        match self {
1089            Number::Fixnum(num) => num.to_f64().map(|num| num.log(f64::E()).into()),
1090            Number::Float(num) => Some(num.log(f64::E()).into()),
1091            Number::BigInt(num) => num.to_f64().map(|num| num.log(f64::E()).into()),
1092            Number::Rational(num) => num.to_f64().map(|num| num.log(f64::E()).into()),
1093        }
1094    }
1095
1096    pub fn sin(&self) -> Option<Number> {
1097        match self {
1098            Number::Fixnum(num) => num.to_f64().map(|num| num.sin().into()),
1099            Number::Float(num) => Some(num.sin().into()),
1100            Number::BigInt(num) => num.to_f64().map(|num| num.sin().into()),
1101            Number::Rational(num) => num.to_f64().map(|num| num.sin().into()),
1102        }
1103    }
1104
1105    pub fn cos(&self) -> Option<Number> {
1106        match self {
1107            Number::Fixnum(num) => num.to_f64().map(|num| num.cos().into()),
1108            Number::Float(num) => Some(num.cos().into()),
1109            Number::BigInt(num) => num.to_f64().map(|num| num.cos().into()),
1110            Number::Rational(num) => num.to_f64().map(|num| num.cos().into()),
1111        }
1112    }
1113
1114    pub fn tan(&self) -> Option<Number> {
1115        match self {
1116            Number::Fixnum(num) => num.to_f64().map(|num| num.tan().into()),
1117            Number::Float(num) => Some(num.tan().into()),
1118            Number::BigInt(num) => num.to_f64().map(|num| num.tan().into()),
1119            Number::Rational(num) => num.to_f64().map(|num| num.tan().into()),
1120        }
1121    }
1122
1123    pub fn asin(&self) -> Option<Number> {
1124        match self {
1125            Number::Fixnum(num) => num.to_f64().map(|num| num.asin().into()),
1126            Number::Float(num) => Some(num.asin().into()),
1127            Number::BigInt(num) => num.to_f64().map(|num| num.asin().into()),
1128            Number::Rational(num) => num.to_f64().map(|num| num.asin().into()),
1129        }
1130    }
1131
1132    pub fn acos(&self) -> Option<Number> {
1133        match self {
1134            Number::Fixnum(num) => num.to_f64().map(|num| num.acos().into()),
1135            Number::Float(num) => Some(num.acos().into()),
1136            Number::BigInt(num) => num.to_f64().map(|num| num.acos().into()),
1137            Number::Rational(num) => num.to_f64().map(|num| num.acos().into()),
1138        }
1139    }
1140
1141    pub fn atan(&self) -> Option<Number> {
1142        match self {
1143            Number::Fixnum(num) => num.to_f64().map(|num| num.atan().into()),
1144            Number::Float(num) => Some(num.atan().into()),
1145            Number::BigInt(num) => num.to_f64().map(|num| num.atan().into()),
1146            Number::Rational(num) => num.to_f64().map(|num| num.atan().into()),
1147        }
1148    }
1149
1150    pub fn atan2(&self, x: Number) -> Option<Number> {
1151        if let Some(x) = x.to_f64() {
1152            match self {
1153                Number::Fixnum(num) => num.to_f64().map(|num| num.atan2(x).into()),
1154                Number::Float(num) => Some(num.atan2(x).into()),
1155                Number::BigInt(num) => num.to_f64().map(|num| num.atan2(x).into()),
1156                Number::Rational(num) => num.to_f64().map(|num| num.atan2(x).into()),
1157            }
1158        } else {
1159            None
1160        }
1161    }
1162
1163    /// sqrt is undefined for complex results
1164    pub fn sqrt(&self) -> Option<Number> {
1165        let result: Option<Number> = match self {
1166            Number::Fixnum(num) => num.to_f64().map(|num| num.sqrt().into()),
1167            Number::Float(num) => Some(num.sqrt().into()),
1168            Number::BigInt(num) => num.to_f64().map(|num| num.sqrt().into()),
1169            Number::Rational(num) => num.to_f64().map(|num| num.sqrt().into()),
1170        };
1171
1172        // convert NaN and infinity to None
1173        if let Some(r) = &result {
1174            if r.to_f64().unwrap().is_finite() {
1175                result
1176            } else {
1177                None
1178            }
1179        } else {
1180            result
1181        }
1182    }
1183}
1184
1185#[cfg(test)]
1186mod tests {
1187    use crate::number::Number;
1188    use num::bigint::BigInt;
1189    use num::traits::FloatConst;
1190    use num::{FromPrimitive, Rational32};
1191    use std::mem;
1192    use std::str::FromStr;
1193
1194    macro_rules! verify {
1195        ($func:expr, $($lhs:expr, $rhs:expr => $result:expr),+) => {{
1196             $(
1197                assert_eq!($func(Number::from($lhs), Number::from($rhs)), Number::from($result),
1198                           "{:?} {:?} != {:?}", $lhs, $rhs, $result);
1199                assert_eq!(mem::discriminant(&$func(Number::from($lhs), Number::from($rhs))),
1200                           mem::discriminant(&Number::from($result)),
1201                           "{:?} {:?} != {:?}", $lhs, $rhs, $result);
1202             )+
1203        }};
1204    }
1205
1206    #[test]
1207    fn to_usize() {
1208        assert!(Number::from(0).to_usize().is_some());
1209        assert!(Number::from(-1).to_usize().is_none());
1210        assert!(Number::from(1.0).to_usize().is_none());
1211        let overflow_num = Number::from(BigInt::from(usize::MAX)) + Number::from(1);
1212        assert!(overflow_num.to_usize().is_none());
1213        assert_eq!(Number::from(Rational32::new(10, 1)).to_usize(), Some(10));
1214    }
1215
1216    #[test]
1217    fn eq() {
1218        assert_eq!(Number::from(100), Number::from(100));
1219        assert_ne!(Number::from(100), Number::from(150));
1220
1221        assert_eq!(Number::from(100.0), Number::from(100));
1222        assert_eq!(Number::from(100), Number::from(100.0));
1223
1224        assert_eq!(
1225            Number::from(100),
1226            Number::from(BigInt::from_str("100").unwrap())
1227        );
1228        assert_eq!(
1229            Number::from(BigInt::from_str("100").unwrap()),
1230            Number::from(100)
1231        );
1232
1233        assert_eq!(
1234            Number::from(100.0),
1235            Number::from(BigInt::from_str("100").unwrap())
1236        );
1237        assert_eq!(
1238            Number::from(BigInt::from_str("100").unwrap()),
1239            Number::from(100.0)
1240        );
1241
1242        assert_eq!(Number::from(Rational32::new(1, 2)), Number::from(0.5));
1243        assert_eq!(Number::from(0.5), Number::from(Rational32::new(1, 2)));
1244
1245        assert_ne!(Number::from(Rational32::new(1, 2)), Number::from(0));
1246    }
1247
1248    #[test]
1249    fn partial_ord() {
1250        assert!(Number::from(200) > Number::from(100));
1251        assert!(!(Number::from(100) > Number::from(100)));
1252        assert!(Number::from(100) >= Number::from(100));
1253        assert!(Number::from(200) >= Number::from(100));
1254
1255        assert!(Number::from(200) > Number::from(100.0));
1256        assert!(Number::from(200.0) > Number::from(100));
1257        assert!(Number::from(200.0) > Number::from(100.0));
1258
1259        assert!(Number::from(200) > Number::new_bigint(100));
1260        assert!(Number::from(200) >= Number::new_bigint(100));
1261        assert!(Number::from(200.0) > Number::new_bigint(100));
1262
1263        assert!(Number::new_bigint(200) > Number::new_bigint(100));
1264        assert!(Number::new_bigint(200) >= Number::new_bigint(100));
1265        assert!(Number::new_bigint(200) > Number::new_bigint(100));
1266
1267        assert!(Number::new_bigint(200) > Number::from(100.0));
1268        assert!(Number::new_bigint(200) >= Number::from(100.0));
1269        assert!(Number::new_bigint(200) > Number::from(100.0));
1270    }
1271
1272    #[test]
1273    fn add() {
1274        let i32_overflow = i32::MAX as i64 + 1;
1275
1276        // FIXNUM + RHS
1277        verify![|x, y| x + y,
1278            100, 50 => 150,
1279            100, i64::MAX => BigInt::from(i64::MAX) + 100,
1280            100, BigInt::from(50) => BigInt::from(150),
1281            100, 50.0 => 150.0,
1282            100, Rational32::from_integer(50) => Rational32::from_integer(150),
1283            i32_overflow, Rational32::from_integer(50) => i32_overflow as f64 + 50_f64
1284        ];
1285
1286        // BIGINT + RHS
1287        verify![|x, y| x + y,
1288            BigInt::from(100), 50 => BigInt::from(150),
1289            BigInt::from(100), i64::MAX => BigInt::from(i64::MAX) + 100,
1290            BigInt::from(100), 50.0 => 150.0,
1291            BigInt::from(100), Rational32::from_integer(50) => BigInt::from(150),
1292            BigInt::from(100), Rational32::new(1, 2) => 100.50
1293        ];
1294
1295        // FLOAT + RHS
1296        verify![|x, y| x + y,
1297            100.0, 50 => 150.0,
1298            100.0, 50.0 => 150.0,
1299            100.0, BigInt::from(50) => 150.0,
1300            100.0, Rational32::from_integer(50) => 150.0
1301        ];
1302
1303        // RATIONAL + RHS
1304        verify![|x, y| x + y,
1305            Rational32::from_integer(100), 50 => Rational32::from_integer(150),
1306            Rational32::from_integer(100), i32_overflow => 100.0 + i32_overflow as f64,
1307            Rational32::from_integer(100), 50.0 => 150.0,
1308            Rational32::from_integer(100), BigInt::from(50) => BigInt::from(150),
1309            Rational32::new(1, 2), BigInt::from(50) => 50.50,
1310            Rational32::from_integer(i32::MAX), Rational32::from_integer(1) => i32::MAX as f64 + 1_f64
1311        ];
1312    }
1313
1314    #[test]
1315    fn mul() {
1316        let i32_overflow = i32::MAX as i64 + 1;
1317
1318        // FIXNUM * RHS
1319        verify![|x, y| x * y,
1320            100, 50 => 5000,
1321            100, i64::MAX => BigInt::from(i64::MAX) * 100,
1322            100, BigInt::from(50) => BigInt::from(5000),
1323            100, 50.0 => 5000.0,
1324            100, Rational32::from_integer(50) => Rational32::from_integer(5000),
1325            i32_overflow, Rational32::from_integer(50) => i32_overflow as f64 * 50_f64
1326        ];
1327
1328        // // BIGINT * RHS
1329        verify![|x, y| x * y,
1330            BigInt::from(100), 50 => BigInt::from(5000),
1331            BigInt::from(100), BigInt::from(50) => BigInt::from(5000),
1332            BigInt::from(100), 50.0 => 5000.0,
1333            BigInt::from(100), Rational32::from_integer(50) => BigInt::from(5000),
1334            BigInt::from(100), Rational32::new(1, 2) => 50.0
1335        ];
1336        //
1337        // // FLOAT * RHS
1338        verify![|x, y| x * y,
1339            100.0, 50 => 5000.0,
1340            100.0, 50.0 => 5000.0,
1341            100.0, BigInt::from(50) => 5000.0,
1342            100.0, Rational32::from_integer(50) => 5000.0
1343        ];
1344        //
1345        // // RATIONAL * RHS
1346        verify![|x, y| x * y,
1347            Rational32::from_integer(100), 50 => Rational32::from_integer(5000),
1348            Rational32::from_integer(100), i32_overflow => 100.0 * i32_overflow as f64,
1349            Rational32::from_integer(100), 50.0 => 5000.0,
1350            Rational32::from_integer(100), BigInt::from(50) => BigInt::from(5000),
1351            Rational32::new(1, 2), BigInt::from(100) => 50.0,
1352            Rational32::from_integer(100), Rational32::from_integer(50) => Rational32::from_integer(5000),
1353            Rational32::from_integer(i32::MAX), Rational32::from_integer(2) => i32::MAX as f64 * 2_f64
1354        ];
1355    }
1356
1357    #[test]
1358    fn sub() {
1359        let i32_overflow = i32::MIN as i64 - 1;
1360
1361        // FIXNUM - RHS
1362        verify![|x, y| x - y,
1363            100, 50 => 50,
1364            -100, i64::MAX => BigInt::from(-i64::MAX) - 100,
1365            100, BigInt::from(50) => BigInt::from(50),
1366            100, 50.0 => 50.0,
1367            100, Rational32::from_integer(50) => Rational32::from_integer(50),
1368            i32::MIN as i64, Rational32::from_integer(50) => i32::MIN as f64 - 50_f64,
1369            i32_overflow, Rational32::from_integer(50) => i32_overflow as f64 - 50_f64
1370        ];
1371
1372        // // BIGINT - RHS
1373        verify![|x, y| x - y,
1374            BigInt::from(100), 50 => BigInt::from(50),
1375            BigInt::from(100), BigInt::from(50) => BigInt::from(50),
1376            BigInt::from(100), 50.0 => 50.0,
1377            BigInt::from(100), Rational32::from_integer(50) => BigInt::from(50),
1378            BigInt::from(100), Rational32::new(1, 2) => 99.50
1379        ];
1380
1381        // FLOAT - RHS
1382        verify![|x, y| x - y,
1383            100.0, 50 => 50.0,
1384            100.0, 50.0 => 50.0,
1385            100.0, BigInt::from(50) => 50.0,
1386            100.0, Rational32::from_integer(50) => 50.0,
1387            100.0, Rational32::new(1, 2) => 99.50
1388        ];
1389
1390        // RATIONAL - RHS
1391        verify![|x, y| x - y,
1392            Rational32::from_integer(100), 50 => Rational32::from_integer(50),
1393            Rational32::from_integer(100), i32::MIN as i64 => 100.0 - i32::MIN as f64,
1394            Rational32::from_integer(100), i32_overflow => 100.0 - i32_overflow as f64,
1395            Rational32::from_integer(100), 50.0 => 50.0,
1396            Rational32::from_integer(100), BigInt::from(50) => BigInt::from(50),
1397            Rational32::new(1, 2), BigInt::from(50) => -49.5,
1398            Rational32::from_integer(100), Rational32::from_integer(50) => Rational32::from_integer(50),
1399            Rational32::from_integer(i32::MIN), Rational32::from_integer(1) => i32::MIN as f64 - 1_f64
1400        ];
1401    }
1402
1403    #[test]
1404    fn div() {
1405        let i32_uflow = i32::MIN as i64 - 1;
1406        let i32_oflow = i32::MAX as i64 + 1;
1407
1408        // FIXNUM / RHS
1409        verify![|x, y| x / y,
1410            100, 50 => Rational32::from_integer(2),
1411            i32_uflow, i32_uflow => 1.0,
1412            i32_oflow, i32_oflow => 1.0,
1413            100, BigInt::from(50) => Rational32::from_integer(2),
1414            i32_oflow, BigInt::from(i32_oflow) => 1.0,
1415            i32_oflow, BigInt::from(2) => i32_oflow as f64 / 2_f64,
1416            100, Rational32::from_integer(50) => Rational32::from_integer(2),
1417            100, Rational32::new(1, 2) => Rational32::from_integer(200),
1418            i32_oflow, Rational32::from_integer(2) => i32_oflow as f64 / 2_f64,
1419            i32::MAX as i64, Rational32::new(1, 2) => i32::MAX as f64 * 2.0,
1420            -100, 1.0 => -100.0
1421        ];
1422
1423        // BIGINT / RHS
1424        verify![|x, y| x / y,
1425            BigInt::from(100), 50 => Rational32::from_integer(2),
1426            BigInt::from(i32_oflow), 2 => i32_oflow as f64 / 2_f64,
1427            BigInt::from(100), i32_oflow => 100 as f64 / i32_oflow as f64,
1428            BigInt::from(100), BigInt::from(50) => Rational32::from_integer(2),
1429            BigInt::from(i32_oflow), BigInt::from(100) => i32_oflow as f64 / 100_f64,
1430            BigInt::from(100), BigInt::from(i32_oflow) => 100_f64 / i32_oflow as f64,
1431            BigInt::from(100), 50.0 => 2.0,
1432            BigInt::from(100), Rational32::from_integer(50) => Rational32::from_integer(2),
1433            BigInt::from(i32_oflow), Rational32::from_integer(50) =>  i32_oflow as f64 / 50_f64,
1434            BigInt::from(i32::MAX), Rational32::new(1, 2) => Number::from(i32::MAX as f64 * 2_f64)
1435        ];
1436
1437        // FLOAT / RHS
1438        verify![|x, y| x / y,
1439            100.0, 50 => 2.0,
1440            100.0, 50.0 => 2.0,
1441            100.0, BigInt::from(50) => 2.0,
1442            100.0, Rational32::from_integer(50) => 2.0,
1443            100.0, Rational32::new(1, 2) => 200.0
1444        ];
1445
1446        // RATIONAL / RHS
1447        verify![|x, y| x / y,
1448            Rational32::from_integer(100), 50 => Rational32::from_integer(2),
1449            Rational32::from_integer(100), i32_oflow => 100_f64 / i32_oflow as f64,
1450            Rational32::from_integer(100), 50_f64 => 2_f64,
1451            Rational32::from_integer(100), BigInt::from(50) => Rational32::from_integer(2),
1452            Rational32::from_integer(100), BigInt::from(i32_oflow) => 100_f64 / i32_oflow as f64,
1453            Rational32::from_integer(100), Rational32::from_integer(50) => Rational32::from_integer(2),
1454            Rational32::from_integer(i32::MAX), Rational32::new(1,2) => i32::MAX as f64 * 2.0
1455        ];
1456    }
1457
1458    #[test]
1459    fn rem() {
1460        // FIXNUM % RHS
1461        assert_eq!(Number::from(100) % Number::from(70), Some(Number::from(30)));
1462        assert_eq!(
1463            Number::from(100) % Number::from(BigInt::from(70)),
1464            Some(Number::from(30))
1465        );
1466        assert_eq!(
1467            Number::from(100) % Number::from(BigInt::from(i64::MAX) + BigInt::from(i64::MAX)),
1468            Some(Number::from(BigInt::from(100)))
1469        );
1470        assert_eq!(
1471            Number::from(100) % Number::from(1.0),
1472            Some(Number::Float(0.0))
1473        );
1474        assert_eq!(
1475            Number::from(100) % Number::from(Rational32::from_integer(70)),
1476            Some(Number::from(30))
1477        );
1478        assert_eq!(
1479            Number::from(100) % Number::from(Rational32::new(1, 2)),
1480            Some(Number::from(0))
1481        );
1482        assert_eq!(
1483            Number::from(1) % Number::from(Rational32::new(2, 5)),
1484            Some(Number::from(Rational32::new(1, 5)))
1485        );
1486        assert_eq!(
1487            Number::from(1) % Number::from(Rational32::new(3, 5)),
1488            Some(Number::from(Rational32::new(2, 5)))
1489        );
1490
1491        // BIGINT % RHS
1492        assert_eq!(
1493            Number::from(BigInt::from(100)) % Number::from(70),
1494            Some(Number::from(30))
1495        );
1496        assert_eq!(
1497            Number::from(BigInt::from(100)) % Number::from(BigInt::from(70)),
1498            Some(Number::from(BigInt::from(30)))
1499        );
1500        // cannot support bigint % float (yet?)
1501        assert_eq!(Number::from(BigInt::from(100)) % Number::from(1.0), None);
1502        assert_eq!(
1503            Number::from(BigInt::from(100)) % Number::from(Rational32::from_integer(70)),
1504            Some(Number::from(BigInt::from(30)))
1505        );
1506        assert_eq!(
1507            Number::from(BigInt::from(1)) % Number::from(Rational32::new(2, 3)),
1508            Some(Number::from(Rational32::new(1, 3)))
1509        );
1510
1511        // RATIONAL % RHS
1512        assert_eq!(
1513            Number::from(Rational32::from_integer(100)) % Number::from(70),
1514            Some(Number::from(30))
1515        );
1516        assert_eq!(
1517            Number::from(Rational32::from_integer(100)) % Number::from(BigInt::from(70)),
1518            Some(Number::from(BigInt::from(30)))
1519        );
1520        assert_eq!(
1521            Number::from(Rational32::from_integer(100))
1522                % Number::from(Rational32::from_integer(70)),
1523            Some(Number::from(Rational32::from_integer(30)))
1524        );
1525        assert_eq!(
1526            Number::from(Rational32::from_integer(1)) % Number::from(Rational32::new(2, 3)),
1527            Some(Number::from(Rational32::new(1, 3)))
1528        );
1529
1530        // FLOAT % RHS
1531        assert_eq!(
1532            Number::from(0.5) % Number::from(70),
1533            Some(Number::from(0.5))
1534        );
1535        assert_eq!(
1536            Number::from(100.0) % Number::from(70),
1537            Some(Number::from(30.0))
1538        );
1539        assert!((Number::from(f64::INFINITY) % Number::from(70))
1540            .unwrap()
1541            .to_f64()
1542            .unwrap()
1543            .is_nan());
1544        assert_eq!(
1545            Number::from(100.0) % Number::from(BigInt::from(70)),
1546            Some(Number::from(30.0))
1547        );
1548        assert_eq!(
1549            Number::from(100.0) % Number::from(BigInt::from(i64::MAX) + BigInt::from(i64::MAX)),
1550            Some(Number::from(100.0))
1551        );
1552        assert_eq!(
1553            Number::from(101.0) % Number::from(2.0),
1554            Some(Number::from(1.0))
1555        );
1556        assert_eq!(
1557            Number::from(100.0) % Number::from(Rational32::from_integer(70)),
1558            Some(Number::from(30.0))
1559        );
1560        assert_eq!(
1561            Number::from(100.0) % Number::from(Rational32::new(1, 2)),
1562            Some(Number::from(0.0))
1563        );
1564        assert_eq!(
1565            Number::from(0.75) % Number::from(Rational32::new(1, 2)),
1566            Some(Number::from(0.25))
1567        );
1568    }
1569
1570    #[test]
1571    fn modulo() {
1572        assert_eq!(
1573            Number::from(-21).modulo(&Number::from(4)),
1574            Some(Number::from(3))
1575        );
1576    }
1577
1578    #[test]
1579    fn round() {
1580        assert_eq!(Number::from(-4.3).floor(), Number::from(-5));
1581        assert_eq!(Number::from(-4.3).ceil(), Number::from(-4));
1582        assert_eq!(Number::from(-4.3).truncate(), Number::from(-4));
1583        assert_eq!(Number::from(-4.3).round(), Number::from(-4));
1584
1585        assert_eq!(Number::from(3.5).floor(), Number::from(3));
1586        assert_eq!(Number::from(3.5).ceil(), Number::from(4));
1587        assert_eq!(Number::from(3.5).truncate(), Number::from(3));
1588        assert_eq!(Number::from(3.5).round(), Number::from(4));
1589
1590        assert_eq!(Number::from(Rational32::new(7, 2)).round(), Number::from(4));
1591    }
1592
1593    #[test]
1594    fn abs() {
1595        assert_eq!(Number::from(-10).abs(), Number::from(10));
1596        assert_eq!(
1597            Number::from(i64::MIN).abs(),
1598            Number::from(BigInt::from(9223372036854775808_u64))
1599        );
1600    }
1601
1602    #[test]
1603    fn sin() {
1604        assert_eq!(Number::from(0).sin(), Some(Number::from(0)));
1605        assert_eq!(
1606            Number::from(f64::FRAC_PI_2()).sin(),
1607            Some(Number::from(1.0))
1608        );
1609        assert_eq!(
1610            Number::from(Rational32::from_integer(0)).sin(),
1611            Some(Number::from(0.0))
1612        );
1613        assert_eq!(Number::from(BigInt::from(0)).sin(), Some(Number::from(0.0)));
1614        assert!(Number::from(BigInt::from_f64(f64::MAX).unwrap() * 2)
1615            .sin()
1616            .unwrap()
1617            .to_f64()
1618            .unwrap()
1619            .is_nan());
1620    }
1621}