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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#![deny(missing_docs)]
//! Crate for creating math functions from string and perform symbolic derivation
use parser::{builder::build, to_rpn, ParsingError};
use simp::simp_node;

mod derivation;
mod display;
mod eval;
mod integration;
pub use crate::eval::{eval_vec_f1d, eval_vec_f2d, eval_vec_f3d};
mod macros;
mod ops;
mod param;
mod parser;
mod simp;
mod traits;

#[derive(Debug, PartialEq)]
/// Representation of a 1D function
pub struct F1D(Func);
#[derive(Debug, PartialEq)]
/// Representation of a 2D function
pub struct F2D(Func);
#[derive(Debug, PartialEq)]
/// Representation of a 3D function
pub struct F3D(Func);

impl F1D {
    /// Creates a new function from a str
    pub fn new(input: &str) -> Result<Self, ParsingError> {
        let mut func = build(to_rpn(input, &['x'])?);
        simp_node(&mut func);
        Ok(F1D(func))
    }
    /// Returns a string in latex format
    pub fn latex(&self) -> String {
        self.0.latex()
    }
}
impl F2D {
    /// Creates a new function from a str
    pub fn new(input: &str) -> Result<Self, ParsingError> {
        let mut func = build(to_rpn(input, &['x', 'y'])?);
        simp_node(&mut func);
        Ok(F2D(func))
    }

    /// Returns a string in latex format
    pub fn latex(&self) -> String {
        self.0.latex()
    }
}

impl F3D {
    /// Creates a new funcction from a str
    pub fn new(input: &str) -> Result<Self, ParsingError> {
        let mut func = build(to_rpn(input, &['x', 'y', 'z'])?);
        simp_node(&mut func);
        Ok(F3D(func))
    }
    /// Returns a string in latex format
    pub fn latex(&self) -> String {
        self.0.latex()
    }
}

impl FND {
    /// Creates a new function from a string
    pub fn new(input: &str, vars: &[char]) -> Result<Self, ParsingError> {
        let mut func = build(to_rpn(input, vars)?);
        simp_node(&mut func);
        Ok(FND {
            vars: vars.to_vec(),
            func,
        })
    }
}

#[derive(Debug, PartialEq)]
/// Representation of an n-dimensional function
pub struct FND {
    vars: Vec<char>,
    func: Func,
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum Func {
    Var(char),
    E,
    PI,
    Num(i32),
    Param(String, f64),
    Add(Vec<Self>),
    Mul(Vec<Self>),
    Pow(Box<Self>, Box<Self>),
    S(FType, Box<Self>),
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum FType {
    Sin,
    Cos,
    Tan,
    Cot,
    Sec,
    Csc,
    ASin,
    ACos,
    ATan,
    Sinh,
    Cosh,
    Tanh,
    Coth,
    Sech,
    Csch,
    ASinh,
    ACosh,
    ATanh,
    Abs,
    Ln,
}

pub(crate) fn gcd(mut n: u32, mut m: u32) -> u32 {
    assert!(n != 0 && m != 0);
    if n == 0 {
        std::mem::swap(&mut n, &mut m);
    }
    while m != 0 {
        if m < n {
            std::mem::swap(&mut m, &mut n);
        }
        m %= n;
    }
    n
}