number_diff/simplify/
classification.rs1use crate::{
2 Elementary::{self, *},
3 Error,
4};
5
6#[derive(Debug, PartialEq)]
7pub enum Category {
8 Exponential,
9 Polynomial,
10 Trigonometric,
11 Constant,
12 ClusterFuck,
13}
14
15impl Elementary {
16 pub fn classify(&self) -> Result<Category, Error> {
17 if self.is_constant() {
18 Ok(Category::Constant)
19 } else if self.is_exponential()? {
20 Ok(Category::Exponential)
21 } else if self.is_polynomial()? {
22 Ok(Category::Polynomial)
23 } else if self.is_trig() {
24 Ok(Category::Trigonometric)
25 } else {
26 Ok(Category::ClusterFuck)
27 }
28 }
29
30 pub fn is_constant(&self) -> bool {
33 match self {
34 Sin(func) => func.is_constant(),
35 Cos(func) => func.is_constant(),
36 Tan(func) => func.is_constant(),
37
38 Sec(func) => func.is_constant(),
39 Csc(func) => func.is_constant(),
40 Cot(func) => func.is_constant(),
41
42 Asin(func) => func.is_constant(),
43 Acos(func) => func.is_constant(),
44 Atan(func) => func.is_constant(),
45
46 Sinh(func) => func.is_constant(),
47 Cosh(func) => func.is_constant(),
48 Tanh(func) => func.is_constant(),
49
50 Add(func1, func2) => func1.is_constant() && func2.is_constant(),
53 Sub(func1, func2) => func1.is_constant() && func2.is_constant(),
54 Mul(func1, func2) => func1.is_constant() && func2.is_constant(),
55 Div(func1, func2) => func1.is_constant() && func2.is_constant(),
56 Pow(func1, func2) => func1.is_constant() && func2.is_constant(),
57 Log(func1, func2) => func1.is_constant() && func2.is_constant(),
58
59 Factorial(func) => func.is_constant(),
60
61 Gamma(func) => func.is_constant(),
62 Polygamma(func, _) => func.is_constant(),
63
64 Abs(func) => func.is_constant(),
65
66 Con(_) => true,
67 X => false,
68 }
69 }
70
71 fn is_linear(&self) -> bool {
73 if let Mul(func1, func2) = self {
74 if (func1.is_constant() && (func2.is_linear() || func2.clone() == X.into()))
75 || (func2.is_constant() && (func1.is_linear() || func1.clone() == X.into()))
76 {
77 return true;
78 }
79 }
80 false
81 }
82
83 pub fn is_digit(&self) -> Result<bool, Error> {
85 if let Con(numb) = self {
86 if numb.fract() == 0.0 {
87 return Ok(true);
88 }
89 }
90 Ok(false)
91 }
92
93 pub fn is_exponential(&self) -> Result<bool, Error> {
95 if let Pow(base, exp) = self {
96 if base.is_constant() && exp.is_linear() {
97 return Ok(true);
98 }
99 }
100 if let Mul(func1, func2) = self {
101 if (func1.is_exponential()? && func2.is_constant())
102 || (func1.is_constant() && func2.is_exponential()?)
103 {
104 return Ok(true);
105 }
106 }
107
108 Ok(false)
109 }
110
111 fn is_polynomial(&self) -> Result<bool, Error> {
114 if let Pow(base, exp) = self {
115 if base.clone().is_polynomial()? && exp.is_digit()? {
116 return Ok(true);
117 }
118 } else if self.clone() == X.into() {
119 return Ok(true);
120 } else if let Con(_) = self {
121 return Ok(true);
122 } else if let Mul(func1, func2) = self {
123 if func1.is_polynomial()? && func2.is_polynomial()? {
124 return Ok(true);
125 }
126 } else if let Add(func1, func2) = self {
127 if func1.is_polynomial()? && func2.is_polynomial()? {
128 return Ok(true);
129 }
130 } else if let Sub(func1, func2) = self {
131 if func1.is_polynomial()? && func2.is_polynomial()? {
132 return Ok(true);
133 }
134 } else if let Div(func1, func2) = self {
135 if func1.is_polynomial()? && func2.is_polynomial()? {
136 return Ok(true);
137 }
138 }
139 Ok(false)
140 }
141
142 fn is_trig(&self) -> bool {
145 match self {
146 Sin(_) => true,
147 Cos(_) => true,
148 Tan(_) => true,
149
150 Sec(_) => true,
151 Csc(_) => true,
152 Cot(_) => true,
153
154 Asin(_) => true,
155 Acos(_) => true,
156 Atan(_) => true,
157
158 Sinh(_) => true,
159 Cosh(_) => true,
160 Tanh(_) => true,
161
162 Add(func1, func2) => func1.is_trig() && func2.is_trig(),
163 Sub(func1, func2) => func1.is_trig() && func2.is_trig(),
164 Mul(func1, func2) => {
165 (func1.is_trig() && func2.is_trig()) || (func1.is_trig() && func2.is_constant()) || (func2.is_trig() && func1.is_constant()) }
169 Div(func1, func2) => {
170 (func1.is_trig() && func2.is_trig())
171 || (func1.is_trig() && func2.is_constant())
172 || (func2.is_trig() && func1.is_constant())
173 }
174 Pow(func1, func2) => func1.is_trig() && func2.is_constant(), Log(func1, func2) => func1.is_constant() && func2.is_trig(), Factorial(_) => false,
178
179 Gamma(_) => false,
180 Polygamma(_, _) => false,
181
182 Abs(_) => false,
183 Con(_) => false,
184 X => false,
185 }
186 }
187}