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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crate::{FType, Func, F1D, F2D, F3D};

impl PartialEq<i32> for Func {
    fn eq(&self, other: &i32) -> bool {
        if let Func::Num(val) = self {
            return val == other;
        }

        false
    }
}
impl PartialOrd<i32> for Func {
    fn partial_cmp(&self, other: &i32) -> Option<std::cmp::Ordering> {
        if let Func::Num(val) = self {
            Some(val.cmp(other))
        } else {
            None
        }
    }
}

impl Eq for Func {}
impl PartialOrd for Func {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Func {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        if let (Func::Pow(base1, exp1), Func::Pow(base2, exp2)) = (self, other) {
            if let Func::Num(e1) = **exp1 {
                if let Func::Num(e2) = **exp2 {
                    if e1 != e2 {
                        return e2.cmp(&e1);
                    } else {
                        return base1.cmp(base2);
                    }
                }
            }
        }

        func_order(self).cmp(&func_order(other))
    }
}

fn func_order(func: &Func) -> u32 {
    match func {
        Func::Num(_) => 0,
        Func::PI => 1,
        Func::E => 2,
        Func::Param(..) => 3,
        Func::Var(char) => char.to_ascii_lowercase() as u32,
        Func::Mul(_) => 123,
        Func::Add(_) => 124,
        Func::S(kind, _) => match kind {
            FType::Abs => 126,
            FType::Ln => 127,
            FType::Sin => 128,
            FType::Cos => 129,
            FType::Tan => 130,
            FType::Cot => 131,
            FType::Sec => 132,
            FType::Csc => 133,
            FType::ASin => 134,
            FType::ACos => 135,
            FType::ATan => 136,
            FType::Sinh => 137,
            FType::Cosh => 138,
            FType::Tanh => 139,
            FType::Coth => 140,
            FType::Sech => 141,
            FType::Csch => 142,
            FType::ASinh => 143,
            FType::ACosh => 144,
            FType::ATanh => 145,
        },
        Func::Pow(_, exp) => {
            if let Func::Num(val) = **exp {
                if val < 0 {
                    147
                } else {
                    146
                }
            } else {
                146
            }
        }
    }
}

impl std::iter::Sum for Func {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Func::Num(0), |acc, func| acc + func)
    }
}

impl std::iter::Product for Func {
    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Func::Num(1), |acc, func| acc * func)
    }
}

impl From<F1D> for F3D {
    fn from(value: F1D) -> Self {
        F3D(value.0)
    }
}
impl From<F2D> for F3D {
    fn from(value: F2D) -> Self {
        F3D(value.0)
    }
}
impl From<F1D> for F2D {
    fn from(value: F1D) -> Self {
        F2D(value.0)
    }
}