1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
mod expr;
mod interpreter;
mod parser;
mod tokenizer;

pub use expr::*;
pub use interpreter::*;
pub use parser::*;
pub use tokenizer::*;

use std::fmt::Debug;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
use std::str::FromStr;

/// Defines the minimum operations and definitions to parse and evaluate expressions.
pub trait Num:
    Debug
    + Clone
    + PartialEq
    + PartialOrd
    + FromStr
    + Add<Output = Self>
    + Sub<Output = Self>
    + Mul<Output = Self>
    + Div<Output = Self>
    + Rem<Output = Self>
    + Neg<Output = Self>
    + AddAssign
    + SubAssign
    + MulAssign
    + DivAssign
{
    /// Returns the additive identity value, 0, for the number.
    fn zero() -> Self;
    /// Returns the multiplicative identity value, 1, for the number.
    fn one() -> Self;
    /// Returns true if the number is a whole integer without a fractional part. E.g. 1 or 3.
    fn is_whole(&self) -> bool;
    /// Returns number to the power of `other`.
    fn pow(self, other: Self) -> Self;
}

macro_rules! impl_num_for_integer {
    ($itype:ty) => {
        impl Num for $itype {
            #[inline(always)]
            fn zero() -> Self {
                0
            }
            #[inline(always)]
            fn one() -> Self {
                1
            }
            #[inline(always)]
            fn is_whole(&self) -> bool {
                true
            }
            #[inline(always)]
            fn pow(self, other: Self) -> Self {
                self.wrapping_pow(other as u32) // Wraps on overflow...
            }
        }
    };
}
impl_num_for_integer!(i8);
impl_num_for_integer!(i16);
impl_num_for_integer!(i32);
impl_num_for_integer!(i64);
impl_num_for_integer!(i128);
impl_num_for_integer!(isize);

macro_rules! impl_num_for_float {
    ($ftype:ty) => {
        impl Num for $ftype {
            #[inline(always)]
            fn zero() -> Self {
                0.0
            }
            #[inline(always)]
            fn one() -> Self {
                1.0
            }
            #[inline(always)]
            fn is_whole(&self) -> bool {
                self.fract() == 0.0
            }
            #[inline(always)]
            fn pow(self, other: Self) -> Self {
                self.powf(other) // inf or -inf if overflowed...
            }
        }
    };
}
impl_num_for_float!(f32);
impl_num_for_float!(f64);