1use crate::Error;
2use std::{
3 f64::consts::{E, PI},
4 sync::Arc,
5};
6
7use crate::Elementary::{self, *};
8
9impl<'a> From<&'a str> for Elementary {
10 fn from(value: &'a str) -> Self {
11 let value: String = value.split_whitespace().collect();
12 Self::to_elementary(&value).unwrap()
13 }
14}
15impl Elementary {
16 fn split_function(value: &str) -> Vec<&str> {
17 let mut interp_slice: Vec<&str> = value.split("").collect();
18 interp_slice.remove(0);
20 interp_slice.pop();
21
22 let mut chunks: Vec<&str> = Vec::new();
23 let mut open_parenthesis = -1;
24
25 let mut cut_index = 0;
26
27 let mut skip = 0;
28 for i in 0..interp_slice.len() {
29 if skip > 0 {
31 skip -= 1;
32 continue;
33 }
34
35 if interp_slice[i] == "(" {
36 if open_parenthesis == -1 {
39 open_parenthesis = 1;
40 } else {
41 open_parenthesis += 1;
44 }
45 } else if interp_slice[i] == ")" {
46 open_parenthesis -= 1
47 }
48
49 if open_parenthesis == 0 {
51 chunks.push(&value[cut_index..=i]);
52
53 cut_index = i + 1;
55
56 open_parenthesis = -1;
58 }
59
60 if open_parenthesis == -1 {
62 if interp_slice[i] == "+"
63 || interp_slice[i] == "-"
64 || interp_slice[i] == "*"
65 || interp_slice[i] == "/"
66 || interp_slice[i] == "^"
67 {
68 chunks.push(interp_slice[i]);
69 cut_index = i + 1;
70 } else if interp_slice[i] == "!" {
71 chunks.push(&value[cut_index..=i]);
72 cut_index = i + 1;
73 } else if interp_slice[i] == "x" {
74 chunks.push(&value[cut_index..=i]);
75 cut_index = i + 1;
76 } else if interp_slice[i] == "e" {
77 chunks.push(&value[cut_index..=i]);
78 cut_index = i + 1;
79 } else if interp_slice[i] == "pi" || interp_slice[i] == "π" {
80 chunks.push("pi");
81 cut_index = i + 1;
82 } else {
83 if let Ok(_) = &value[cut_index..=i].parse::<f64>() {
85 let mut last_index = i;
87 'index: for j in i + 1..=interp_slice.len() {
88 if let Ok(_) = &value[cut_index..j].parse::<f64>() {
89 last_index = j - 1;
90 } else {
91 break 'index;
92 }
93 }
94
95 chunks.push(&value[cut_index..=last_index]);
97
98 skip = last_index - i;
101 cut_index = last_index + 1;
104 }
105 }
106 }
107 }
108
109 if chunks.is_empty() {
110 chunks.push(value);
111 }
112
113 chunks
114 }
115
116 fn to_elementary(string: &str) -> Result<Self, Error> {
117 let strings = Self::split_function(string);
118
119 let mut functions: Vec<ElemRef> = strings
120 .clone()
121 .iter()
122 .map(|s| Self::parse_function(s).unwrap())
123 .collect();
124
125 let mut iteration = 0;
126
127 while functions.len() != 1 {
129 if iteration >= 10000 {
130 return Err(Error::ParseError(String::from(format!(
131 "Iteration limit reached while parsing function: {string}",
132 ))));
133 } else {
134 iteration += 1;
135 }
136 if functions.contains(&ElemRef::Pow) {
139 for i in (0..functions.len()).rev() {
140 if i >= functions.len() {
143 continue;
144 }
145 if functions[i] == ElemRef::Pow {
146 let replacement_func = ElemRef::Function(Pow(
147 Arc::new(functions[i - 1].clone().convert()?),
148 Arc::new(functions[i + 1].clone().convert()?),
149 ));
150 functions.remove(i + 1);
151 functions.remove(i);
152 functions.remove(i - 1);
153 functions.insert(i - 1, replacement_func);
154 }
155 }
156
157 continue;
158 }
159
160 if functions.contains(&ElemRef::Factorial) {
163 iterate_operation(&mut functions, ElemRef::Factorial)?;
164 continue;
165 }
166
167 if functions.contains(&ElemRef::Mul) {
169 iterate_operation(&mut functions, ElemRef::Mul)?;
170 continue;
171 }
172
173 for i in 0..functions.len() {
179 if i < functions.len() - 1 {
180 if let (ElemRef::Function(func1), ElemRef::Function(func2)) =
181 (&functions[i], &functions[i + 1])
182 {
183 let replacement_func = ElemRef::Function(Mul(
185 Arc::new(func1.to_owned()),
186 Arc::new(func2.to_owned()),
187 ));
188
189 functions.remove(i + 1);
191 functions.remove(i);
192 functions.insert(i, replacement_func);
193 }
194 }
195 }
196 if functions.contains(&ElemRef::Div) {
198 iterate_operation(&mut functions, ElemRef::Div)?;
199 continue;
200 }
201
202 if functions.contains(&ElemRef::Add) {
204 iterate_operation(&mut functions, ElemRef::Add)?;
205 continue;
206 }
207
208 if functions.contains(&ElemRef::Sub) {
210 iterate_operation(&mut functions, ElemRef::Sub)?;
211 continue;
212 }
213 }
214
215 functions
216 .pop()
217 .expect("Couldn't find a function to parse")
218 .convert()
219 }
220
221 fn parse_function(string: &str) -> Result<ElemRef, Error> {
222 let mut string = string.to_lowercase();
223
224 if &string[..1] == "(" {
226 while &string[..1] == "(" {
227 string = string[1..string.len() - 1].to_string();
228 }
229 return Ok(ElemRef::Function(Self::to_elementary(&string)?));
230 }
231
232 if string == "x" {
234 return Ok(ElemRef::Function(X));
235 } else if let Ok(number) = string.parse::<f64>() {
236 return Ok(ElemRef::Function(Con(number)));
237 }
238
239 match &string[..] {
240 "^" => Ok(ElemRef::Pow),
242 "*" => Ok(ElemRef::Mul),
243 "/" => Ok(ElemRef::Div),
244 "+" => Ok(ElemRef::Add),
245 "-" => Ok(ElemRef::Sub),
246 "e" => Ok(ElemRef::Function(Con(E))),
248 "pi" => Ok(ElemRef::Function(Con(PI))),
249 "!" => Ok(ElemRef::Factorial),
250 _ => {
251 let (func, cont) = split_first(&string, "(");
254
255 let mut graphemes: Vec<&str> = cont.split("").collect();
257 graphemes.remove(0);
259 graphemes.pop();
260 let cont: String = graphemes.iter().map(|x| *x).collect();
261
262 match func {
263 "sin" => Ok(ElemRef::Function(Sin(Arc::new(Self::to_elementary(
264 &cont,
265 )?)))),
266 "cos" => Ok(ElemRef::Function(Cos(Arc::new(Self::to_elementary(
267 &cont,
268 )?)))),
269 "tan" => Ok(ElemRef::Function(Tan(Arc::new(Self::to_elementary(
270 &cont,
271 )?)))),
272 "sec" => Ok(ElemRef::Function(Sec(Arc::new(Self::to_elementary(
273 &cont,
274 )?)))),
275 "csc" => Ok(ElemRef::Function(Csc(Arc::new(Self::to_elementary(
276 &cont,
277 )?)))),
278 "cot" => Ok(ElemRef::Function(Cot(Arc::new(Self::to_elementary(
279 &cont,
280 )?)))),
281 "asin" => Ok(ElemRef::Function(Asin(Arc::new(Self::to_elementary(
282 &cont,
283 )?)))),
284 "acos" => Ok(ElemRef::Function(Acos(Arc::new(Self::to_elementary(
285 &cont,
286 )?)))),
287 "atan" => Ok(ElemRef::Function(Atan(Arc::new(Self::to_elementary(
288 &cont,
289 )?)))),
290 "sinh" => Ok(ElemRef::Function(Sinh(Arc::new(Self::to_elementary(
291 &cont,
292 )?)))),
293 "cosh" => Ok(ElemRef::Function(Cosh(Arc::new(Self::to_elementary(
294 &cont,
295 )?)))),
296 "tanh" => Ok(ElemRef::Function(Tanh(Arc::new(Self::to_elementary(
297 &cont,
298 )?)))),
299 "ln" => Ok(ElemRef::Function(Log(
300 Arc::new(Con(E)), Arc::new(Self::to_elementary(&cont)?),
302 ))),
303 "abs" => Ok(ElemRef::Function(Abs(Arc::new(Self::to_elementary(
304 &cont,
305 )?)))),
306 "sqrt" => Ok(ElemRef::Function(Pow(
307 Arc::new(Self::to_elementary(&cont)?),
308 Arc::new(Con(0.5)),
309 ))),
310 "d" => Ok(ElemRef::Function(
311 Self::to_elementary(&cont)?.derivative_unsimplified(),
312 )),
313 _ => Err(Error::ParseError(format!(
314 "Function identifier '{func}' not recognized"
315 ))),
316 }
317 }
318 }
319 }
320}
321
322fn iterate_operation(functions: &mut Vec<ElemRef>, operation: ElemRef) -> Result<(), Error> {
325 if functions.contains(&operation) {
326 for i in 0..functions.len() {
327 if i >= functions.len() {
328 continue;
329 }
330
331 if functions[i] == operation {
332 let replacement_func = match operation {
333 ElemRef::Mul => ElemRef::Function(Mul(
334 Arc::new(functions[i - 1].clone().convert()?),
335 Arc::new(functions[i + 1].clone().convert()?),
336 )),
337 ElemRef::Div => ElemRef::Function(Div(
338 Arc::new(functions[i - 1].clone().convert()?),
339 Arc::new(functions[i + 1].clone().convert()?),
340 )),
341 ElemRef::Add => ElemRef::Function(Add(
342 Arc::new(functions[i + 1].clone().convert()?),
343 Arc::new(functions[i - 1].clone().convert()?),
344 )),
345 ElemRef::Sub => {
346 if i > 0 {
347 ElemRef::Function(Sub(
348 Arc::new(functions[i - 1].clone().convert()?),
349 Arc::new(functions[i + 1].clone().convert()?),
350 ))
351 } else {
352 ElemRef::Function(functions[i + 1].clone().convert()? * (-1 as f64))
353 }
354 }
355 ElemRef::Factorial => {
356 if i > 0 {
357 ElemRef::Function(Factorial(functions[i - 1].clone().convert()?.into()))
358 } else {
359 return Err(Error::ParseError(String::from(
360 "Factorial function must be applied to another function",
361 )));
362 }
363 }
364 _ => unimplemented!("No such operation"), };
366
367 if operation == ElemRef::Factorial {
368 println!("testing - {replacement_func:?}");
369 functions.remove(i);
372 functions.remove(i - 1);
373 functions.insert(i - 1, replacement_func)
374 } else {
375 functions.remove(i + 1);
377 functions.remove(i);
378 if i > 0 {
379 functions.remove(i - 1);
380 functions.insert(i - 1, replacement_func);
382 } else {
383 functions.insert(i, replacement_func)
385 }
386 }
387 }
388 }
389 }
390 Ok(())
391}
392
393#[derive(Debug, Clone, PartialEq)]
395enum ElemRef {
396 Function(Elementary),
397 Pow,
398 Mul,
399 Div,
400 Add,
401 Sub,
402 Factorial,
403}
404impl ElemRef {
405 fn convert(self) -> Result<Elementary, Error> {
406 match self {
407 Self::Function(elem) => Ok(elem),
408 _ => Err(Error::ParseError(String::from(
409 "Cannot convert operation to elementary function",
410 ))),
411 }
412 }
413}
414
415fn split_first<'a>(string: &'a String, indentifier: &'a str) -> (&'a str, &'a str) {
418 let slice: Vec<&str> = string.split("").collect();
419
420 let mut index = 0;
421 for (i, s) in slice.iter().enumerate().take(string.len()) {
424 if *s == indentifier {
425 index = i;
426 break;
427 }
428 }
429
430 string.split_at(index - 1)
431}