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
#![warn(missing_docs)]

//! Crate for math Funcs
/// Contains context
pub mod ctx;
/// Utils for printing functions
pub mod display;
mod operations;

mod macros;
/// Operations betwen unctions
mod ops;
mod parser;
pub(crate) mod simp;
mod traits;
use ctx::Ctx;

/// Representation of a Func
#[derive(Clone, PartialEq, Eq, Debug)]
pub(crate) enum Func {
    X,
    Y,
    Z,
    E,
    PI,
    Num(i32),
    Param(String),
    Add(Vec<Self>),
    Mul(Vec<Self>, Vec<Self>),
    Pow(Box<Self>, Box<Self>),
    Special { kind: FuncType, argument: Box<Self> },
}

#[derive(Debug, PartialEq)]
/// Representation of a Func with 1 variable
pub struct F1D(Func, Ctx);
#[derive(Debug, PartialEq)]
/// Representation of a Func with 2 variables
pub struct F2D(Func, Ctx);
#[derive(PartialEq, Debug)]
/// Representation of a Func with 3 variables
pub struct F3D(Func, Ctx);

#[derive(Clone, Eq, PartialEq, Debug)]
/// Types of special built-in Funcs
pub(crate) enum FuncType {
    Sin,
    Cos,
    Tan,
    Cot,
    Sec,
    Csc,
    ASin,
    ACos,
    ATan,
    Sinh,
    Cosh,
    Tanh,
    Coth,
    Sech,
    Csch,
    ASinh,
    ACosh,
    ATanh,
    Abs,
    /// Natural logarithm
    Ln,
}

#[derive(Clone, PartialEq, Debug)]
pub(crate) enum Op {
    Add,
    Sub,
    Mul,
    Div,
    Pow,
    Comp,
}

impl Op {
    fn priority(&self) -> u8 {
        match self {
            Op::Add => 4,
            Op::Sub => 4,
            Op::Mul => 3,
            Op::Div => 3,
            Op::Pow => 2,
            Op::Comp => 1,
        }
    }
}

/// Func to approximate f64 to the nth decimal place
pub fn approx(num: f64, digits: u32) -> f64 {
    let y = 10i32.pow(digits) as f64;
    (num * y).round() / y
}

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)
    }
}