equation_solver/
item.rs

1use crate::equation::Group;
2
3/// An item represents a single item in an equation.
4#[derive(Debug, Clone)]
5pub enum Item {
6    /// A value is a number.
7    Value(f64),
8    /// A variable is a variable that can be replaced later.
9    Variable(String),
10    /// An operator is an operator that can be used in an equation (i.e. +).
11    Operator(Operator),
12    /// A group is a group of items (like those inside of bracets).
13    Group(Group),
14}
15
16/// An operator is an operator that can be used in an equation (i.e. +).
17#[derive(Debug, Clone, PartialEq)]
18pub enum Operator {
19    /// A left-associative operator is an operator that requires a left and right of the equation (i.e. +).
20    LeftAssociative(LeftAssociativeOperator),
21    /// A functional operator is an operator that requires only a right of the equation (i.e. sin).
22    Functional(FunctionalOperator),
23}
24
25/// A left-associative operator is an operator that requires a left and right of the equation (i.e. +).
26#[derive(Debug, Clone, PartialEq)]
27pub enum LeftAssociativeOperator {
28    /// The addition operator.
29    Add,
30    /// The subtraction operator.
31    Subtract,
32    /// The multiplication operator.
33    Multiply,
34    /// The division operator.
35    Divide,
36    /// The exponentiation operator.
37    Power,
38    /// The root operator. (not used)
39    Root,
40}
41
42/// A functional operator is an operator that requires only a right of the equation (i.e. sin).
43#[derive(Debug, Clone, PartialEq)]
44pub enum FunctionalOperator {
45    /// The Log (base 10)
46    Log,
47    /// The natural log (base e)
48    Ln,
49    /// The sine function.
50    Sin,
51    /// The cosine function.
52    Cos,
53    /// The tangent function.
54    Tan,
55    /// The cotangent function.
56    Cot,
57    /// The secant function.
58    Sec,
59    /// The cosecant function.
60    Csc,
61    /// The inverse sin function.
62    Arcsin,
63    /// The inverse cosine function.
64    Arccos,
65    /// The inverse tangent function.
66    Arctan,
67    /// The inverse cotangent function.
68    Arccot,
69    /// The inverse secant function.
70    Arcsec,
71    /// The inverse cosecant function.
72    Arccsc,
73}
74
75impl From<f64> for Item {
76    fn from(val: f64) -> Self {
77        Item::Value(val)
78    }
79}
80
81impl From<String> for Item {
82    fn from(val: String) -> Self {
83        Item::Variable(val)
84    }
85}
86
87impl From<Operator> for Item {
88    fn from(val: Operator) -> Self {
89        Item::Operator(val)
90    }
91}
92
93impl From<Group> for Item {
94    fn from(val: Group) -> Self {
95        Item::Group(val)
96    }
97}
98
99impl From<LeftAssociativeOperator> for Operator {
100    fn from(val: LeftAssociativeOperator) -> Self {
101        Operator::LeftAssociative(val)
102    }
103}
104
105impl From<FunctionalOperator> for Operator {
106    fn from(val: FunctionalOperator) -> Self {
107        Operator::Functional(val)
108    }
109}
110
111impl From<LeftAssociativeOperator> for Item {
112    fn from(val: LeftAssociativeOperator) -> Self {
113        Item::Operator(val.into())
114    }
115}
116
117impl From<FunctionalOperator> for Item {
118    fn from(val: FunctionalOperator) -> Self {
119        Item::Operator(val.into())
120    }
121}
122
123impl From<Vec<Item>> for Item {
124    fn from(val: Vec<Item>) -> Self {
125        Item::Group(val.into())
126    }
127}
128
129impl FunctionalOperator {
130    /// Returns the value of the operator given the right value.
131    pub fn evaluate(&self, x: f64) -> f64 {
132        match self {
133            FunctionalOperator::Log => x.log10(),
134            FunctionalOperator::Ln => x.ln(),
135            FunctionalOperator::Sin => x.sin(),
136            FunctionalOperator::Cos => x.cos(),
137            FunctionalOperator::Tan => x.tan(),
138            FunctionalOperator::Cot => x.tan().recip(),
139            FunctionalOperator::Sec => x.cos().recip(),
140            FunctionalOperator::Csc => x.sin().recip(),
141            FunctionalOperator::Arcsin => x.asin(),
142            FunctionalOperator::Arccos => x.acos(),
143            FunctionalOperator::Arctan => x.atan(),
144            FunctionalOperator::Arccot => x.atan().recip(),
145            FunctionalOperator::Arcsec => x.acos().recip(),
146            FunctionalOperator::Arccsc => x.asin().recip(),
147        }
148    }
149}
150
151impl LeftAssociativeOperator {
152    /// Checks weather the order of the operator is correct. (for pemdas)
153    pub fn is_of_order(&self, order: &u8) -> bool {
154        // pemdas
155        // pe = 0
156        // md = 1
157        // as = 2
158
159        match self {
160            LeftAssociativeOperator::Add | LeftAssociativeOperator::Subtract => *order == 2,
161            LeftAssociativeOperator::Multiply | LeftAssociativeOperator::Divide => *order == 1,
162            LeftAssociativeOperator::Power | LeftAssociativeOperator::Root => *order == 0,
163        }
164    }
165    /// Returns the value of the operator given the left and right values.
166    pub fn eval(&self, lhs: f64, rhs: f64) -> f64 {
167        match self {
168            LeftAssociativeOperator::Add => lhs + rhs,
169            LeftAssociativeOperator::Subtract => lhs - rhs,
170            LeftAssociativeOperator::Multiply => lhs * rhs,
171            LeftAssociativeOperator::Divide => lhs / rhs,
172            LeftAssociativeOperator::Power => lhs.powf(rhs),
173            LeftAssociativeOperator::Root => rhs.powf(lhs.recip()),
174        }
175    }
176}