1use crate::{
2 complex::{
3 NumStr,
4 NumStr::{
5 And, Comma, Converse, Conversion, Division, Equal, Exponent, Func, Greater,
6 GreaterEqual, Implies, InternalMultiplication, LeftBracket, LeftCurlyBracket, Lesser,
7 LesserEqual, Matrix, Minus, Modulo, Multiplication, Nand, NearEqual, Nor, Not,
8 NotEqual, Num, Or, Plus, PlusMinus, Range, RightBracket, RightCurlyBracket, Root,
9 ShiftLeft, ShiftRight, Tetration, Vector, Xor,
10 },
11 pow_nth,
12 },
13 functions::functions,
14 math::do_math,
15 units::{
16 GraphType, HowGraphing, Notation::SmallEngineering, Number, Options, Variable, is_unit,
17 prefixes, to_unit,
18 },
19};
20use rug::{
21 Complex,
22 float::Special::{Infinity, Nan},
23 ops::CompleteRound,
24};
25#[allow(clippy::type_complexity)]
26#[allow(clippy::too_many_arguments)]
27pub fn input_var(
28 input: &str,
29 vars: &[Variable],
30 sumrec: &mut Vec<(isize, String)>,
31 bracket: &mut isize,
32 options: Options,
33 print: bool,
34 depth: usize,
35 blacklist: Vec<char>,
36 isgraphing: bool,
37 collectvars: &mut Vec<(isize, usize)>,
38 solven: Option<usize>,
39 ison: Option<usize>,
40) -> Result<
41 (
42 Vec<NumStr>,
43 Vec<(String, Vec<NumStr>)>,
44 HowGraphing,
45 bool,
46 Option<String>,
47 ),
48 &'static str,
49> {
50 let mut sumvar: Option<String> = None;
51 let mut graph = HowGraphing::default();
52 let prec = (options.prec, options.prec);
53 let mut funcvars = Vec::new();
54 if input.starts_with("history")
55 || input.starts_with("his")
56 || input.starts_with("onaxis")
57 || input.starts_with("exit")
58 || input.starts_with("quit")
59 || input.starts_with("break")
60 || input.is_empty()
61 {
62 return Err(" ");
63 }
64 let mut undf = false;
65 let mut funcfailed = false;
66 let mut absfailed = false;
67 let mut scientific = false;
68 let mut abs: Vec<(usize, isize)> = Vec::new();
69 let mut neg = false;
70 let n1 = Complex::with_val(options.prec, -1);
71 let mut pow = String::new();
72 let mut exp = (String::new(), 0);
73 let mut subfact: Vec<isize> = Vec::new();
74 let mut err = "";
75 let mut solves = Vec::new();
76 let mut solvesp = Vec::new();
77 let mut iso = Vec::new();
78 let mut isop = Vec::new();
79 let mut slope = Vec::new();
80 let mut chars = input
81 .replace('[', "(car{")
82 .replace(']', "})")
83 .chars()
84 .collect::<Vec<char>>();
85 if chars.ends_with(&['^']) {
86 chars.pop();
87 }
88 if chars.iter().filter(|a| **a == '|').count() % 2 == 1 {
89 if chars.ends_with(&['|']) {
90 chars.insert(0, '|')
91 } else {
92 chars.push('|')
93 }
94 }
95 let mut sarea = 0;
96 let mut output: Vec<NumStr> = Vec::new();
97 let mut stack_end = Vec::new();
98 let mut stack_start = Vec::new();
99 let mut i = 0;
100 let mut piecewise = 0;
101 let mut pwr: (bool, isize, isize) = (false, 0, 0);
102 while !chars.is_empty() && chars[0].is_ascii_whitespace() {
103 chars.remove(0);
104 }
105 while i < chars.len() {
106 if chars[i].is_ascii_whitespace() {
107 if chars.len().saturating_sub(1) == i {
108 chars.remove(i);
109 } else if (chars[i - 1].is_alphanumeric() || matches!(chars[i - 1], ')' | '}'))
110 && (chars[i + 1].is_alphanumeric() || matches!(chars[i + 1], '(' | '{'))
111 {
112 chars[i] = '*'
113 } else if chars[i - 1] == '+' && chars[i + 1] == '-' {
114 chars.drain(i - 1..=i);
115 } else {
116 chars.remove(i);
117 }
118 } else {
119 i += 1;
120 }
121 }
122 for c in &chars {
123 match c {
124 '(' => stack_end.insert(0, ')'),
125 '{' => stack_end.insert(0, '}'),
126 ')' | '}' => {
127 if !stack_end.is_empty() && stack_end[0] == *c {
128 stack_end.remove(0);
129 } else {
130 match c {
131 ')' => stack_start.push('('),
132 '}' => stack_start.push('{'),
133 _ => {}
134 }
135 }
136 }
137 _ => {}
138 }
139 }
140 chars.extend(stack_end);
141 for i in stack_start {
142 chars.insert(0, i);
143 }
144 i = 0;
145 let mut sum = (0, String::new());
146 let functions = functions();
147 let mut ceilfoor = 0;
148 let mut solvesn = if let Some(n) = solven {
149 n
150 } else {
151 chars.iter().filter(|a| a == &&'~').count()
152 };
153 let mut ison = if let Some(n) = ison {
154 n
155 } else {
156 chars.iter().filter(|a| a == &&'=').count()
157 };
158 'main: while i < chars.len() {
159 let c = chars[i];
160 if !matches!(
161 c,
162 '⁰' | '₀'
163 | '⁹'
164 | '₉'
165 | '⁸'
166 | '₈'
167 | '⁷'
168 | '₇'
169 | '⁶'
170 | '₆'
171 | '⁵'
172 | '₅'
173 | '⁴'
174 | '₄'
175 | '³'
176 | '₃'
177 | '²'
178 | '₂'
179 | '¹'
180 | '₁'
181 | '⁻'
182 | 'ⁱ'
183 ) && !pow.is_empty()
184 {
185 let i = pow.matches('i').count() % 4;
186 pow = pow.replace('i', "");
187 if pow.is_empty() {
188 pow = '1'.to_string();
189 }
190 match output.last() {
191 Some(Num(_)) | Some(Vector(_)) | Some(Matrix(_)) => output.push(Exponent),
192 Some(Func(s))
193 if matches!(s.as_str(), "x" | "y" | "w" | "rnd" | "rand" | "epoch")
194 || sumrec.iter().any(|v| &v.1 == s) =>
195 {
196 output.push(Exponent)
197 }
198 _ => {}
199 }
200 output.push(NumStr::new(Number::from(
201 match Complex::parse_radix(pow.as_bytes(), options.base.0) {
202 Ok(n) => n.complete(prec),
203 _ => return Err("exponent error"),
204 } * pow_nth(
205 Complex::with_val(options.prec, (0, 1)),
206 Complex::with_val(options.prec, i),
207 ),
208 None,
209 )));
210 pow = String::new();
211 }
212 if c == '.' && i + 1 < chars.len() && chars[i + 1] == '.' {
213 output.push(Range);
214 i += 2;
215 continue;
216 }
217 if c.is_ascii_digit()
218 || c == '.'
219 || (options.base.0 > 10
220 && (97..=97 + (options.base.0 as u8 - 11)).contains(&(chars[i] as u8)))
221 {
222 let mut num = String::new();
223 let mut dot = false;
224 while i < chars.len() {
225 if is_digit(chars[i], options.base.0) {
226 num.push(chars[i]);
227 } else if chars[i] == '.' {
228 if i + 1 < chars.len() && chars[i + 1] == '.' {
229 break;
230 } else if dot {
231 return Err("invalid digit");
232 } else {
233 dot = true;
234 num.push('.')
235 }
236 } else {
237 break;
238 }
239 i += 1;
240 }
241 if num.starts_with('.') {
242 num.insert(0, '0')
243 }
244 place_multiplier(&mut output, sumrec, &sumvar);
245 if neg {
246 if chars.len() > i
247 && (chars[i] == '^'
248 || chars[i] == '!'
249 || (chars.len() > i + 1 && chars[i] == '/' && chars[i + 1] == '/'))
250 {
251 output.push(NumStr::new(Number::from(n1.clone(), None)));
252 output.push(InternalMultiplication);
253 } else {
254 num.insert(0, '-');
255 }
256 neg = false;
257 }
258 if num == "0" && i != chars.len() && chars[i] == '⁻' {
259 num.insert(0, '-');
260 i += 1;
261 }
262 output.push(NumStr::new(Number::from(
263 match Complex::parse_radix(num.clone(), options.base.0) {
264 Ok(n) => n.complete(prec),
265 Err(_) => return Err("probably radix error"),
266 },
267 None,
268 )));
269 if scientific {
270 output.push(RightBracket);
271 scientific = false;
272 }
273 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i || chars[i] != '^') {
274 for _ in 0..pwr.2 {
275 output.push(RightBracket);
276 }
277 pwr.0 = false;
278 pwr.2 = 0
279 }
280 if !subfact.is_empty() && subfact[0] == 0 {
281 output.push(RightBracket);
282 output.push(RightBracket);
283 subfact.remove(0);
284 }
285 continue;
286 }
287 if !c.is_alphabetic() && !matches!(c, '°' | '@' | '∫' | '$' | '¢') {
288 if !output.is_empty() {
289 if let Func(s) = output.last_mut().unwrap() {
290 if functions.contains(s.as_str()) && !sumrec.iter().any(|a| a.1 == *s) {
291 if i + 4 < chars.len()
292 && chars[i] == '^'
293 && chars[i + 1] == '('
294 && chars[i + 2] == '-'
295 && chars[i + 3] == '1'
296 && chars[i + 4] == ')'
297 {
298 s.insert(0, 'a');
299 i += 5;
300 continue;
301 }
302 if i + 2 < chars.len()
303 && chars[i] == '^'
304 && chars[i + 1] == '-'
305 && chars[i + 2] == '1'
306 {
307 s.insert(0, 'a');
308 i += 3;
309 continue;
310 }
311 if i + 1 < chars.len() && chars[i] == '⁻' && chars[i + 1] == '¹' {
312 s.insert(0, 'a');
313 i += 2;
314 continue;
315 }
316 if i + 1 < chars.len()
317 && chars[i] == '^'
318 && (is_digit(chars[i + 1], options.base.0) || chars[i + 1] == '-')
319 {
320 let pos = chars
321 .iter()
322 .skip(i + 1)
323 .position(|&c| c == '(' || c == ')' || c == ',');
324 if pos.is_none() {
325 return Err("bad exponent");
326 }
327 exp = (chars[i + 1..=i + pos.unwrap()].iter().collect(), *bracket);
328 i += pos.unwrap() + 1;
329 continue;
330 }
331 }
332 }
333 }
334 match c {
335 '√' => output.push(Func("sqrt".to_string())),
336 '∛' => output.push(Func("cbrt".to_string())),
337 '¼' => output.push(NumStr::new(Number::from(
338 Complex::with_val(options.prec, 0.25),
339 None,
340 ))),
341 '½' => output.push(NumStr::new(Number::from(
342 Complex::with_val(options.prec, 0.5),
343 None,
344 ))),
345 '¾' => output.push(NumStr::new(Number::from(
346 Complex::with_val(options.prec, 0.75),
347 None,
348 ))),
349 '⅒' => output.push(NumStr::new(Number::from(
350 Complex::with_val(options.prec, 1) / 10,
351 None,
352 ))),
353 '⅕' => output.push(NumStr::new(Number::from(
354 Complex::with_val(options.prec, 1) / 5,
355 None,
356 ))),
357 '⅖' => output.push(NumStr::new(Number::from(
358 Complex::with_val(options.prec, 2) / 5,
359 None,
360 ))),
361 '⅗' => output.push(NumStr::new(Number::from(
362 Complex::with_val(options.prec, 3) / 5,
363 None,
364 ))),
365 '⅘' => output.push(NumStr::new(Number::from(
366 Complex::with_val(options.prec, 4) / 5,
367 None,
368 ))),
369 '⅐' => output.push(NumStr::new(Number::from(
370 Complex::with_val(options.prec, 7).recip(),
371 None,
372 ))),
373 '⅑' => output.push(NumStr::new(Number::from(
374 Complex::with_val(options.prec, 9).recip(),
375 None,
376 ))),
377 '⅓' => output.push(NumStr::new(Number::from(
378 Complex::with_val(options.prec, 3).recip(),
379 None,
380 ))),
381 '⅔' => output.push(NumStr::new(Number::from(
382 Complex::with_val(options.prec, 1.5).recip(),
383 None,
384 ))),
385 '⅙' => output.push(NumStr::new(Number::from(
386 Complex::with_val(options.prec, 6).recip(),
387 None,
388 ))),
389 '⅚' => output.push(NumStr::new(Number::from(
390 Complex::with_val(options.prec, 5) / 6,
391 None,
392 ))),
393 '⅛' => output.push(NumStr::new(Number::from(
394 Complex::with_val(options.prec, 0.125),
395 None,
396 ))),
397 '⅜' => output.push(NumStr::new(Number::from(
398 Complex::with_val(options.prec, 3) / 8,
399 None,
400 ))),
401 '⅝' => output.push(NumStr::new(Number::from(
402 Complex::with_val(options.prec, 5) / 8,
403 None,
404 ))),
405 '⅞' => output.push(NumStr::new(Number::from(
406 Complex::with_val(options.prec, 7) / 8,
407 None,
408 ))),
409 '⅟' => {
410 output.push(NumStr::new(Number::from(
411 Complex::with_val(options.prec, 1),
412 None,
413 )));
414 output.push(Division)
415 }
416 '↉' => output.push(NumStr::new(Number::from(Complex::new(options.prec), None))),
417 '⁰' | '₀' => pow.push('0'),
418 '⁹' | '₉' => pow.push('9'),
419 '⁸' | '₈' => pow.push('8'),
420 '⁷' | '₇' => pow.push('7'),
421 '⁶' | '₆' => pow.push('6'),
422 '⁵' | '₅' => pow.push('5'),
423 '⁴' | '₄' => pow.push('4'),
424 '³' | '₃' => pow.push('3'),
425 '²' | '₂' => pow.push('2'),
426 '¹' | '₁' => pow.push('1'),
427 '⁻' => pow.push('-'),
428 '&' if i != 0
429 && i + 1 < chars.len()
430 && chars[i + 1] == '&'
431 && !matches!(chars[i + 1], ')' | '}' | ']') =>
432 {
433 i += 1;
434 output.push(And);
435 }
436 '¬' => {
437 output.push(Not);
438 }
439 '=' if i != 0
440 && i + 1 < chars.len()
441 && (!matches!(chars[i + 1], ')' | '}' | ']') || *bracket != 0) =>
442 {
443 macro_rules! iso {
444 () => {
445 *bracket += 1;
446 isop.insert(0, (*bracket, false));
447 if i + 1 == chars.len()
448 || (chars[i + 1] == '0'
449 && (i + 2 == chars.len() || chars[i + 2] == ')'))
450 {
451 i += 1;
452 isop[0].1 = true;
453 } else if i != 0
454 && chars[i - 1] == '0'
455 && (i - 1 == 0 || chars[i - 1] == '(')
456 {
457 output.pop();
458 isop[0].1 = true;
459 } else {
460 if i + 1 > chars.len() || chars[i + 1] != ')' {
461 output.push(Minus);
462 }
463 output.push(LeftBracket);
464 }
465 let mut brac = 0;
466 let mut j = 0;
467 for (i, f) in output.iter().rev().enumerate() {
468 match f {
469 LeftBracket if brac == 1 => {
470 j = output.len() - i;
471 break;
472 }
473 LeftBracket => brac += 1,
474 RightBracket => brac -= 1,
475 _ => {}
476 }
477 }
478 if let Some(n) = sumvar.clone() {
479 sumrec.push((*bracket, n.clone()));
480 output.insert(j, Comma);
481 output.insert(j, Func(n));
482 } else {
483 collectvars.insert(0, (*bracket, j + 2))
484 }
485 output.insert(j, LeftBracket);
486 output.insert(j, Func("isolate".to_string()));
487 };
488 }
489 if chars[i + 1] == '=' {
490 ison -= 1;
491 i += 1;
492 if i + 1 < chars.len() && chars[i + 1] == '=' {
493 i += 1;
494 ison -= 1;
495 iso!();
496 } else {
497 output.push(Equal);
498 }
499 } else if chars[i - 1] == '>' {
500 output.push(GreaterEqual);
501 } else if chars[i - 1] == '<' {
502 output.push(LesserEqual);
503 } else if *bracket == 0 {
504 return Ok((Vec::new(), Vec::new(), HowGraphing::default(), true, None));
505 } else if i == 0
506 || matches!(chars[i - 1], '(' | '{' | '[')
507 || (chars[i - 1] == '|' && !abs.is_empty())
508 {
509 place_multiplier(&mut output, sumrec, &sumvar);
510 output.push(Func("isolate".to_string()));
511 output.push(LeftBracket);
512 *bracket += 1;
513 collectvars.insert(0, (*bracket, output.len()));
514 iso.insert(0, *bracket);
515 } else {
516 iso!();
517 }
518 ison -= 1;
519 }
520 '{' => {
521 *bracket += 1;
522 place_multiplier(&mut output, sumrec, &sumvar);
523 output.push(LeftCurlyBracket);
524 }
525 '}' => {
526 *bracket -= 1;
527 output.push(RightCurlyBracket);
528 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
529 for _ in 0..pwr.2 {
530 output.push(RightBracket);
531 }
532 pwr.0 = false;
533 pwr.2 = 0
534 }
535 }
536 '≈' if i != 0
537 && i + 1 != chars.len()
538 && !matches!(chars[i + 1], ')' | '}' | ']') =>
539 {
540 output.push(NearEqual)
541 }
542 '±' if i + 1 != chars.len() && !matches!(chars[i + 1], ')' | '}' | ']') => {
543 if output.is_empty()
544 || matches!(
545 output.last().unwrap(),
546 Comma | LeftBracket | LeftCurlyBracket
547 )
548 {
549 output.push(NumStr::new(Number::from(Complex::new(options.prec), None)))
550 }
551 output.push(PlusMinus)
552 }
553 '*' if i != 0
554 && i + 1 != chars.len()
555 && !matches!(chars[i + 1], ')' | '}' | ']') =>
556 {
557 if chars[i + 1] == '*' {
558 if chars.len() > i + 2 {
559 output.push(Exponent);
560 }
561 i += 1;
562 } else {
563 output.push(Multiplication);
564 }
565 }
566 '/' if i != 0
567 && i + 1 != chars.len()
568 && !matches!(chars[i + 1], ')' | '}' | ']') =>
569 {
570 if chars[i + 1] == '/' {
571 output.push(Root);
572 i += 1;
573 } else if chars[i + 1] == '-' {
574 place_multiplier(&mut output, sumrec, &sumvar);
575 output.push(NumStr::new(Number::from(n1.clone(), None)));
576 output.push(Division);
577 i += 1;
578 } else {
579 output.push(Division);
580 }
581 }
582 '+' if i != 0
583 && i + 1 != chars.len()
584 && (chars[i - 1].is_alphanumeric()
585 || (!output.is_empty() && *output.last().unwrap() == RightBracket)
586 || matches!(
587 chars[i - 1],
588 '}' | ']' | ')' | '@' | '°' | '$' | '¢' | '%' | '\'' | '`'
589 ))
590 && chars[i - 1]
591 != if options.notation == SmallEngineering {
592 'e'
593 } else {
594 'E'
595 }
596 && !matches!(chars[i + 1], ')' | '}' | ']') =>
597 {
598 if chars[i + 1] == '-' {
599 if output.is_empty()
600 || matches!(
601 output.last().unwrap(),
602 Comma | LeftBracket | LeftCurlyBracket
603 )
604 {
605 output.push(NumStr::new(Number::from(Complex::new(options.prec), None)))
606 }
607 i += 1;
608 output.push(PlusMinus)
609 } else {
610 output.push(Plus)
611 }
612 }
613 '+' if i + 1 < chars.len()
614 && chars[i + 1] == '-'
615 && !matches!(chars[i + 1], ')' | '}' | ']') =>
616 {
617 if output.is_empty()
618 || matches!(
619 output.last().unwrap(),
620 Comma | LeftBracket | LeftCurlyBracket
621 )
622 {
623 output.push(NumStr::new(Number::from(Complex::new(options.prec), None)))
624 }
625 i += 1;
626 output.push(PlusMinus)
627 }
628 '<' if i != 0
629 && i + 1 < chars.len()
630 && chars[i + 1] != '='
631 && !matches!(chars[i + 1], ')' | '}' | ']') =>
632 {
633 if chars[i + 1] == '<' {
634 if i + 2 < chars.len() {
635 output.push(ShiftLeft);
636 i += 1;
637 }
638 } else {
639 output.push(Lesser);
640 }
641 }
642 '>' if i != 0
643 && i + 1 < chars.len()
644 && chars[i + 1] != '='
645 && !matches!(chars[i + 1], ')' | '}' | ']') =>
646 {
647 if chars[i + 1] == '>' {
648 if i + 2 < chars.len() {
649 output.push(ShiftRight);
650 i += 1;
651 }
652 } else {
653 output.push(Greater);
654 }
655 }
656 '-' if i + 1 < chars.len() && !matches!(chars[i + 1], ')' | '}' | ']') => {
657 if options.units && chars[i + 1] == '>' {
658 output.push(Conversion);
659 i += 1;
660 } else if (i != 0 && chars[i - 1] == '^')
661 || (i > 1 && chars[i - 1] == '/' && chars[i - 2] == '/')
662 {
663 output.push(LeftBracket);
664 output.push(NumStr::new(Number::from(n1.clone(), None)));
665 output.push(InternalMultiplication);
666 pwr.0 = true;
667 pwr.1 = *bracket;
668 pwr.2 += 1;
669 } else if i == 0
670 || !(chars[i - 1]
671 != if options.notation == SmallEngineering {
672 'e'
673 } else {
674 'E'
675 }
676 && (chars[i - 1].is_alphanumeric()
677 || (!output.is_empty() && *output.last().unwrap() == RightBracket)
678 || matches!(
679 chars[i - 1],
680 '}' | ']' | ')' | '@' | '°' | '$' | '¢' | '%' | '\'' | '`'
681 )))
682 {
683 if i + 1 != chars.len()
684 && matches!(chars[i + 1], '(' | '{' | '[' | '|' | '-' | '!')
685 {
686 output.push(NumStr::new(Number::from(n1.clone(), None)));
687 output.push(InternalMultiplication);
688 } else {
689 neg = true;
690 }
691 } else {
692 output.push(Minus);
693 }
694 }
695 '^' if !output.is_empty()
696 && i + 1 != chars.len()
697 && !matches!(chars[i + 1], ')' | '}' | ']') =>
698 {
699 if chars[i + 1] == '^' {
700 if chars.len() > i + 2 {
701 output.push(Tetration)
702 }
703 i += 1;
704 } else {
705 output.push(Exponent);
706 }
707 }
708 '⌈' if i + 1 != chars.len() => {
709 *bracket += 1;
710 ceilfoor += 2;
711 output.push(LeftBracket);
712 output.push(Func("ceil".to_string()));
713 output.push(LeftBracket);
714 }
715 '⌊' if i + 1 != chars.len() => {
716 *bracket += 1;
717 ceilfoor += 2;
718 output.push(LeftBracket);
719 output.push(Func("floor".to_string()));
720 output.push(LeftBracket);
721 }
722 '⌉' if i != 0 => {
723 *bracket -= 1;
724 ceilfoor -= 2;
725 output.push(RightBracket);
726 output.push(RightBracket);
727 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
728 for _ in 0..pwr.2 {
729 output.push(RightBracket);
730 }
731 pwr.0 = false;
732 pwr.2 = 0
733 }
734 }
735 '⌋' if i != 0 => {
736 *bracket -= 1;
737 ceilfoor -= 2;
738 output.push(RightBracket);
739 output.push(RightBracket);
740 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
741 for _ in 0..pwr.2 {
742 output.push(RightBracket);
743 }
744 pwr.0 = false;
745 pwr.2 = 0
746 }
747 }
748 '(' if i + 1 != chars.len() => {
749 *bracket += 1;
750 if !subfact.is_empty() {
751 subfact[0] = *bracket;
752 }
753 place_multiplier(&mut output, sumrec, &sumvar);
754 output.push(LeftBracket);
755 }
756 '~' => {
757 if i == 0
758 || matches!(chars[i - 1], '(' | '{' | '[')
759 || (chars[i - 1] == '|' && !abs.is_empty())
760 {
761 place_multiplier(&mut output, sumrec, &sumvar);
762 output.push(Func("solve".to_string()));
763 output.push(LeftBracket);
764 *bracket += 1;
765 collectvars.insert(0, (*bracket, output.len()));
766 if i + 1 != chars.len() && chars[i + 1] == '~' {
767 i += 1;
768 solvesn -= 1;
769 if i + 1 != chars.len() && chars[i + 1] == '~' {
770 i += 1;
771 solvesn -= 1;
772 solves.insert(0, (*bracket, 2));
773 } else {
774 solves.insert(0, (*bracket, 1));
775 }
776 } else {
777 solves.insert(0, (*bracket, 0));
778 }
779 } else {
780 *bracket += 1;
781 if i + 1 != chars.len() && chars[i + 1] == '~' {
782 i += 1;
783 solvesn -= 1;
784 if i + 1 != chars.len() && chars[i + 1] == '~' {
785 i += 1;
786 solvesn -= 1;
787 solvesp.insert(0, (*bracket, 2, false));
788 } else {
789 solvesp.insert(0, (*bracket, 1, false));
790 }
791 } else {
792 solvesp.insert(0, (*bracket, 0, false));
793 }
794 if i + 1 == chars.len()
795 || (chars[i + 1] == '0'
796 && (i + 2 == chars.len() || chars[i + 2] == ')'))
797 {
798 i += 1;
799 solvesp[0].2 = true;
800 } else if i != 0
801 && chars[i - 1] == '0'
802 && (i - 1 == 0 || chars[i - 1] == '(')
803 {
804 output.pop();
805 solvesp[0].2 = true;
806 } else {
807 if i + 1 > chars.len() || chars[i + 1] != ')' {
808 output.push(Minus);
809 }
810 output.push(LeftBracket);
811 }
812 let mut brac = 0;
813 let mut j = 0;
814 for (i, f) in output.iter().rev().enumerate() {
815 match f {
816 LeftBracket if brac == 1 => {
817 j = output.len() - i;
818 break;
819 }
820 LeftBracket => brac += 1,
821 RightBracket => brac -= 1,
822 _ => {}
823 }
824 }
825 if let Some(n) = sumvar.clone() {
826 sumrec.push((*bracket, n.clone()));
827 output.insert(j, Comma);
828 output.insert(j, Func(n));
829 } else {
830 collectvars.insert(0, (*bracket, j + 2))
831 }
832 output.insert(j, LeftBracket);
833 output.insert(j, Func("solve".to_string()));
834 }
835 solvesn -= 1;
836 }
837 ')' if i != 0 => {
838 if !solves.is_empty() && solves[0].0 == *bracket {
839 if solves[0].1 == 2 {
840 output.push(Comma);
841 output.push(NumStr::new(Number::from(
842 Complex::with_val(options.prec, (Nan, 1)),
843 None,
844 )));
845 } else if solves[0].1 == 1 {
846 output.push(Comma);
847 output.push(NumStr::new(Number::from(
848 Complex::with_val(options.prec, Nan),
849 None,
850 )));
851 }
852 output.push(RightBracket);
853 solves.remove(0);
854 }
855 if !iso.is_empty() && iso[0] == *bracket {
856 output.push(RightBracket);
857 iso.remove(0);
858 }
859 if !collectvars.is_empty() && collectvars[0].0 == *bracket {
860 output.insert(collectvars[0].1, Comma);
861 collectvars.remove(0);
862 }
863 if piecewise == *bracket as usize {
864 piecewise = 0;
865 }
866 if !subfact.is_empty() && subfact[0] == *bracket {
867 subfact.remove(0);
868 output.push(RightBracket);
869 output.push(RightBracket);
870 }
871 if !solvesp.is_empty() && solvesp[0].0 == *bracket {
872 if !solvesp[0].2 {
873 output.push(RightBracket);
874 }
875 if solvesp[0].1 == 2 {
876 output.push(Comma);
877 output.push(NumStr::new(Number::from(
878 Complex::with_val(options.prec, (Nan, 1)),
879 None,
880 )));
881 } else if solvesp[0].1 == 1 {
882 output.push(Comma);
883 output.push(NumStr::new(Number::from(
884 Complex::with_val(options.prec, Nan),
885 None,
886 )));
887 }
888 output.push(RightBracket);
889 solvesp.remove(0);
890 }
891 if !isop.is_empty() && isop[0].0 == *bracket {
892 if !isop[0].1 {
893 output.push(RightBracket);
894 }
895 output.push(RightBracket);
896 isop.remove(0);
897 }
898 *bracket -= 1;
899 output.push(RightBracket);
900 if !exp.0.is_empty() && exp.1 == *bracket {
901 output.push(Exponent);
902 output.push(NumStr::new(Number::from(
903 match Complex::parse_radix(exp.0.as_bytes(), options.base.0) {
904 Ok(n) => n.complete(prec),
905 _ => return Err("exponent error"),
906 },
907 None,
908 )));
909 exp = (String::new(), 0);
910 }
911 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
912 for _ in 0..pwr.2 {
913 output.push(RightBracket);
914 }
915 pwr.0 = false;
916 pwr.2 = 0
917 }
918 }
919 '|' => {
920 if !abs.is_empty()
921 && abs[0].1 == *bracket
922 && abs[0].0 != i - 1
923 && can_abs(&output, vars)
924 {
925 *bracket -= 1;
926 if (i + 2 >= chars.len() || chars[i + 1] != '^') && pwr.1 == *bracket {
927 for _ in 0..pwr.2 {
928 output.push(RightBracket);
929 }
930 pwr = (false, 0, 0);
931 }
932 output.push(RightBracket);
933 output.push(RightBracket);
934 abs.remove(0);
935 } else if i + 1 != chars.len()
936 && chars[i + 1] == '|'
937 && i != 0
938 && !matches!(chars[i - 1], '(' | '{' | '[' | '|')
939 {
940 if i + 2 != chars.len() {
941 output.push(Or);
942 }
943 i += 2;
944 continue;
945 } else if i + 1 != chars.len() {
946 *bracket += 1;
947 if !subfact.is_empty() {
948 subfact[0] = *bracket;
949 }
950 place_multiplier(&mut output, sumrec, &sumvar);
951 output.push(LeftBracket);
952 output.push(Func("norm".to_string()));
953 output.push(LeftBracket);
954 abs.insert(0, (i, *bracket));
955 }
956 }
957 '!' => {
958 if i + 1 < chars.len() && chars[i + 1] == '=' {
959 output.push(NotEqual);
960 i += 1;
961 } else if i != 0
962 && (chars[i - 1].is_alphanumeric()
963 || matches!(chars[i - 1], '\'' | '`')
964 || (!output.is_empty()
965 && matches!(
966 output.last().unwrap(),
967 RightBracket | RightCurlyBracket
968 )))
969 {
970 if !output.is_empty()
971 && matches!(output.last().unwrap(), RightBracket | RightCurlyBracket)
972 {
973 let mut count = 0;
974 for (j, c) in output.iter().enumerate().rev() {
975 match c {
976 LeftBracket | LeftCurlyBracket => {
977 count -= 1;
978 }
979 RightBracket | RightCurlyBracket => {
980 count += 1;
981 }
982 _ => {}
983 }
984 if count == 0 {
985 if j != 0 {
986 if let Func(s) = &output[j - 1] {
987 if !s.is_empty()
988 && s.chars().next().unwrap().is_alphabetic()
989 {
990 output.insert(j - 1, LeftBracket);
991 if i + 1 != chars.len() && chars[i + 1] == '!' {
992 i += 1;
993 output.insert(j, LeftBracket);
994 output
995 .insert(j, Func("doublefact".to_string()));
996 } else {
997 output.insert(j, LeftBracket);
998 output.insert(j, Func("fact".to_string()));
999 }
1000 output.push(RightBracket);
1001 output.push(RightBracket);
1002 i += 1;
1003 continue 'main;
1004 }
1005 }
1006 }
1007 output.insert(j, LeftBracket);
1008 if i + 1 != chars.len() && chars[i + 1] == '!' {
1009 i += 1;
1010 output.insert(j, Func("doublefact".to_string()));
1011 } else {
1012 output.insert(j, Func("fact".to_string()));
1013 }
1014 output.push(RightBracket);
1015 i += 1;
1016 continue 'main;
1017 }
1018 }
1019 }
1020 output.insert(output.len().saturating_sub(1), LeftBracket);
1021 if i + 1 != chars.len() && chars[i + 1] == '!' {
1022 i += 1;
1023 output.insert(
1024 output.len().saturating_sub(1),
1025 Func("doublefact".to_string()),
1026 );
1027 } else {
1028 output.insert(output.len().saturating_sub(1), Func("fact".to_string()));
1029 }
1030 output.insert(output.len().saturating_sub(1), LeftBracket);
1031 output.push(RightBracket);
1032 output.push(RightBracket);
1033 } else if i != chars.len().saturating_sub(1)
1034 && (chars[i + 1].is_alphanumeric()
1035 || matches!(chars[i + 1], '(' | '{' | '|' | '-' | '!'))
1036 {
1037 output.push(LeftBracket);
1038 output.push(Func("subfact".to_string()));
1039 output.push(LeftBracket);
1040 subfact.insert(0, 0);
1041 }
1042 }
1043 ',' if i != 0 && i + 1 != chars.len() && chars[i + 1] != ')' => {
1044 for (i, sum) in sumrec.clone().iter().enumerate() {
1045 if &sum.0 == bracket {
1046 if sarea > 0 {
1047 sarea -= 1;
1048 } else {
1049 sumrec.remove(i);
1050 }
1051 break;
1052 }
1053 }
1054 if scientific {
1055 output.push(RightBracket);
1056 scientific = false;
1057 }
1058 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
1059 for _ in 0..pwr.2 {
1060 output.push(RightBracket);
1061 }
1062 pwr.0 = false;
1063 pwr.2 = 0
1064 }
1065 if !subfact.is_empty() && subfact[0] == 0 {
1066 subfact.remove(0);
1067 output.push(RightBracket);
1068 output.push(RightBracket);
1069 }
1070 output.push(Comma)
1071 }
1072 '%' if i != 0 => {
1073 if i + 1 == chars.len()
1074 || matches!(chars[i + 1], '+' | '-' | '*' | '/' | '^' | '}' | ')')
1075 {
1076 let mut j: isize = -1;
1077 let mut bracket = 0;
1078 for (k, n) in output.iter().rev().enumerate() {
1079 match n {
1080 RightBracket => {
1081 bracket += 1;
1082 }
1083 LeftBracket => {
1084 bracket -= 1;
1085 }
1086 Plus | Minus | PlusMinus if bracket == 0 => {
1087 j = ((output.len() - k) - 1) as isize;
1088 break;
1089 }
1090 _ => {}
1091 }
1092 }
1093 if j != -1 {
1094 output.insert(
1095 j as usize,
1096 NumStr::new(Number::from(Complex::with_val(options.prec, 1), None)),
1097 );
1098 output.insert(j as usize, LeftBracket);
1099 output.insert(j as usize, Multiplication);
1100 }
1101 match output.last() {
1102 Some(Num(_))
1103 | Some(Func(_))
1104 | Some(RightBracket)
1105 | Some(RightCurlyBracket) => {}
1106 _ => output.push(NumStr::new(Number::from(
1107 Complex::with_val(options.prec, 1),
1108 None,
1109 ))),
1110 }
1111 output.push(Multiplication);
1112 output.push(NumStr::new(Number::from(
1113 Complex::with_val(options.prec, 1) / 100,
1114 None,
1115 )));
1116 if j != -1 {
1117 output.push(RightBracket);
1118 }
1119 } else if !matches!(chars[i + 1], ')' | '}' | ']') {
1120 output.push(Modulo)
1121 }
1122 }
1123 '∞' => output.push(NumStr::new(Number::from(
1124 Complex::with_val(options.prec, Infinity),
1125 None,
1126 ))),
1127 '#' => {
1128 graph.graph = true;
1129 break 'main;
1130 }
1131 _ => {}
1132 }
1133 i += 1;
1134 continue;
1135 }
1136 let mut depthcheck = false;
1137 let mut word = String::new();
1138 let mut countv = 0;
1139 for c in chars[i..].iter() {
1140 if c == &'@' {
1141 depthcheck = !depthcheck;
1142 } else if c.is_alphabetic()
1143 || matches!(*c, '°' | '\'' | '`' | '_' | '∫' | '$' | '¢')
1144 || (c == &'2' && word == "atan")
1145 {
1146 word.push(*c);
1147 } else if !depthcheck {
1148 break;
1149 }
1150 countv += 1;
1151 }
1152 let wordv = word.clone();
1153 let var_overrule = if i + countv < chars.len()
1154 && (matches!(chars[i + countv], '(' | '{' | '[')
1155 || (!funcfailed && chars[i + countv] == '|'))
1156 {
1157 !vars.iter().any(|a| {
1158 if a.name.contains(&'(') {
1159 a.name[..a.name.iter().position(|c| c == &'(').unwrap()]
1160 .iter()
1161 .collect::<String>()
1162 == word
1163 } else {
1164 a.name.iter().collect::<String>() == word
1165 }
1166 })
1167 } else {
1168 !vars
1169 .iter()
1170 .any(|a| a.name.iter().collect::<String>() == word)
1171 };
1172 let mut is_slope = false;
1173 let mut is_area = false;
1174 let mut nth = 0;
1175 if var_overrule {
1176 if (word.ends_with('x')
1177 && word != "max"
1178 && !word.ends_with("lx")
1179 && !word.ends_with("lux"))
1180 || (word.ends_with('y')
1181 && word != "any"
1182 && word != "unity"
1183 && word != "identity"
1184 && !word.ends_with("day")
1185 && !word.ends_with("gravity")
1186 && !word.ends_with("ly")
1187 && !word.ends_with("henry")
1188 && !word.ends_with("Gy")
1189 && !word.ends_with("gray"))
1190 || (word.ends_with('w') && word != "pw" && word != "lambertw" && word != "skew")
1191 || (word.ends_with('z')
1192 && !word.ends_with("Hz")
1193 && !word.ends_with("hertz")
1194 && !word.ends_with("oz"))
1195 {
1196 countv -= 1;
1197 word.pop();
1198 }
1199 while word.ends_with('\'') {
1200 is_slope = true;
1201 nth += 1;
1202 countv -= 1;
1203 word.pop();
1204 }
1205 while word.ends_with('`') {
1206 is_area = true;
1207 nth += 1;
1208 countv -= 1;
1209 word.pop();
1210 }
1211 if is_area && is_slope {
1212 return Err("both ' and `");
1213 }
1214 }
1215 if (word == "piecewise" || word == "pw") && piecewise == 0 {
1216 piecewise = *bracket as usize + 1;
1217 } else if matches!(
1218 word.as_str(),
1219 "∫" | "area"
1220 | "surfacearea"
1221 | "sarea"
1222 | "solve"
1223 | "length"
1224 | "slope"
1225 | "taylor"
1226 | "sum"
1227 | "iter"
1228 | "extrema"
1229 | "summation"
1230 | "prod"
1231 | "production"
1232 | "vec"
1233 | "mat"
1234 | "Σ"
1235 | "Π"
1236 | "D"
1237 | "integrate"
1238 | "arclength"
1239 | "lim"
1240 | "set"
1241 | "limit"
1242 | "isolate"
1243 ) && chars.len() > i + countv + 1
1244 && var_overrule
1245 && chars[i + countv] == '('
1246 {
1247 let mut place = 0;
1248 let mut count2 = 0;
1249 for c in &chars[i + countv + 1..] {
1250 if c == &',' && count2 == 0 {
1251 place += 1;
1252 } else if c == &'(' || c == &'{' {
1253 count2 += 1;
1254 } else if c == &')' || c == &'}' {
1255 if count2 == 0 {
1256 break;
1257 }
1258 count2 -= 1;
1259 }
1260 }
1261 if match word.as_str() {
1262 "integrate" | "vec" | "arclength" | "mat" | "prod" | "production" | "iter"
1263 | "length" | "∫" | "area" | "sum" | "Σ" | "summation" | "Π" | "taylor" => {
1264 place >= 3
1265 }
1266 "sarea" | "surfacearea" => place >= 6,
1267 "solve" | "extrema" | "isolate" => place >= 1,
1268 "D" | "slope" | "lim" | "limit" | "set" => place >= 2,
1269 _ => place > 0,
1270 } {
1271 sum.0 = *bracket + 1;
1272 sum.1 = String::new();
1273 let mut count = 0;
1274 for c in chars[i + countv + 1..].iter() {
1275 count += 1;
1276 if c.is_alphabetic() || matches!(c, '\'' | '`' | '_') {
1277 sum.1.push(*c);
1278 } else if c == &',' {
1279 break;
1280 } else {
1281 *bracket += 1;
1282 place_multiplier(&mut output, sumrec, &sumvar);
1283 output.push(Func(word.clone()));
1284 output.push(LeftBracket);
1285 collectvars.insert(0, (*bracket, output.len()));
1286 i += countv + 1;
1287 continue 'main;
1288 }
1289 }
1290 if !sum.1.is_empty() {
1291 if sumrec.is_empty() {
1292 sumrec.push(sum.clone())
1293 } else {
1294 for (i, j) in sumrec.iter().enumerate() {
1295 if j.1.chars().count() <= sum.1.len() {
1296 sumrec.insert(i, sum.clone());
1297 break;
1298 }
1299 }
1300 }
1301 place_multiplier(&mut output, sumrec, &sumvar);
1302 output.push(Func(word.clone()));
1303 output.push(LeftBracket);
1304 if sumrec.iter().any(|c| c.0 == -1) {
1305 output.push(Func("@".to_owned() + &sum.1));
1306 } else {
1307 output.push(Func(sum.1));
1308 }
1309 output.push(Comma);
1310 if matches!(word.as_str(), "surfacearea" | "sarea") {
1311 sarea += 1;
1312 sum.0 = *bracket + 1;
1313 sum.1 = String::new();
1314 for c in chars[i + countv + count + 1..].iter() {
1315 count += 1;
1316 if c.is_alphabetic() || matches!(c, '\'' | '`' | '_') {
1317 sum.1.push(*c);
1318 } else if c == &',' {
1319 break;
1320 }
1321 }
1322 for (i, j) in sumrec.iter().enumerate() {
1323 if j.1.chars().count() <= sum.1.len() {
1324 sumrec.insert(i, sum.clone());
1325 break;
1326 }
1327 }
1328 if sumrec.iter().any(|c| c.0 == -1) {
1329 output.push(Func("@".to_owned() + &sum.1));
1330 } else {
1331 output.push(Func(sum.1));
1332 }
1333 output.push(Comma);
1334 }
1335 *bracket += 1;
1336 i += count + countv + 1;
1337 continue;
1338 }
1339 } else if place == 0 {
1340 if matches!(word.as_str(), "extrema" | "solve" | "isolate") {
1341 *bracket += 1;
1342 place_multiplier(&mut output, sumrec, &sumvar);
1343 output.push(Func(word.clone()));
1344 output.push(LeftBracket);
1345 collectvars.insert(0, (*bracket, output.len()));
1346 i += countv + 1;
1347 continue 'main;
1348 }
1349 } else {
1350 *bracket += 1;
1351 place_multiplier(&mut output, sumrec, &sumvar);
1352 output.push(Func(word.clone()));
1353 output.push(LeftBracket);
1354 collectvars.insert(0, (*bracket, output.len()));
1355 i += countv + 1;
1356 continue 'main;
1357 }
1358 }
1359 let (mut unit, mul);
1360 let mut num = 0;
1361 let var_overrule = if i + countv + nth < chars.len()
1362 && (matches!(chars[i + countv + nth], '(' | '{' | '[')
1363 || (!funcfailed && chars[i + countv + nth] == '|'))
1364 {
1365 !vars.iter().any(|a| {
1366 if a.name.contains(&'(') {
1367 a.name[..a.name.iter().position(|c| c == &'(').unwrap()]
1368 .iter()
1369 .collect::<String>()
1370 == word.trim_end_matches('\'').trim_end_matches('`')
1371 } else {
1372 a.name.iter().collect::<String>() == word
1373 }
1374 })
1375 } else {
1376 !vars.iter().any(|a| {
1377 a.name.iter().collect::<String>().starts_with(&word)
1378 && (a.name.len() == word.chars().count()
1379 || (i + (a.name.len().saturating_sub(1)) < chars.len()
1380 && chars[i..i + a.name.len()] == a.name))
1381 })
1382 };
1383 if sumrec.iter().any(|a| {
1384 if wordv == a.1 {
1385 num = a.0;
1386 word.clone_from(&a.1);
1387 true
1388 } else {
1389 false
1390 }
1391 }) || (!vars
1392 .iter()
1393 .any(|c| c.name.iter().collect::<String>().split('(').next().unwrap() == wordv)
1394 && !functions.contains(wordv.as_str())
1395 && sumrec.iter().any(|a| {
1396 if wordv.starts_with(&a.1) && !a.1.is_empty() {
1397 num = a.0;
1398 word.clone_from(&a.1);
1399 true
1400 } else {
1401 false
1402 }
1403 }))
1404 {
1405 place_multiplier(&mut output, sumrec, &sumvar);
1406 if neg {
1407 output.push(NumStr::new(Number::from(n1.clone(), None)));
1408 output.push(InternalMultiplication);
1409 neg = false;
1410 }
1411 i += if c == '@' {
1412 chars[i + 1..].iter().position(|a| a == &'@').unwrap_or(0) + 2
1413 } else {
1414 word.chars().count()
1415 };
1416 if num > 0 && sumrec.iter().any(|c| c.0 == -1) {
1417 output.push(Func("@".to_owned() + &word));
1418 } else {
1419 output.push(Func(word));
1420 }
1421 if pwr.0 && pwr.1 == *bracket && chars.len() < i && chars[i] != '^' {
1422 for _ in 0..pwr.2 {
1423 output.push(RightBracket);
1424 }
1425 pwr.0 = false;
1426 pwr.2 = 0
1427 }
1428 if scientific {
1429 output.push(RightBracket);
1430 scientific = false;
1431 }
1432 if !subfact.is_empty() && subfact[0] == 0 {
1433 subfact.remove(0);
1434 output.push(RightBracket);
1435 output.push(RightBracket);
1436 }
1437 } else if var_overrule
1438 && ((functions.contains(word.as_str())
1439 && i + countv < chars.len()
1440 && (matches!(
1441 chars[i + countv],
1442 'x' | 'y' | 'w' | 'z' | '(' | '|' | '{' | '0'..='9' | '⁻' | '*' | '\'' | '`'
1443 ) || (chars[i + countv] == '^' && chars[i] != 'C' && countv != 1)))
1444 || matches!(
1445 word.to_ascii_lowercase().as_str(),
1446 "rnd" | "rand" | "epoch" | "inf" | "true" | "false" | "nan"
1447 ))
1448 {
1449 place_multiplier(&mut output, sumrec, &sumvar);
1450 if neg {
1451 output.push(NumStr::new(Number::from(n1.clone(), None)));
1452 output.push(InternalMultiplication);
1453 neg = false;
1454 }
1455 i += countv;
1456 if matches!(
1457 word.to_ascii_lowercase().as_str(),
1458 "rnd" | "rand" | "epoch" | "inf" | "true" | "false" | "nan"
1459 ) {
1460 match word.to_ascii_lowercase().as_str() {
1461 "nan" | "NaN" => {
1462 output.push(NumStr::new(Number::from(
1463 Complex::with_val(options.prec, Nan),
1464 None,
1465 )));
1466 }
1467 "true" => {
1468 output.push(NumStr::new(Number::from(
1469 Complex::with_val(options.prec, 1),
1470 None,
1471 )));
1472 }
1473 "false" => {
1474 output.push(NumStr::new(Number::from(Complex::new(options.prec), None)));
1475 }
1476 "inf" => {
1477 output.push(NumStr::new(Number::from(
1478 Complex::with_val(options.prec, Infinity),
1479 None,
1480 )));
1481 }
1482 _ => output.push(Func(word)),
1483 }
1484 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
1485 for _ in 0..pwr.2 {
1486 output.push(RightBracket);
1487 }
1488 pwr.0 = false;
1489 pwr.2 = 0
1490 }
1491 if scientific {
1492 output.push(RightBracket);
1493 scientific = false;
1494 }
1495 if !subfact.is_empty() && subfact[0] == 0 {
1496 subfact.remove(0);
1497 output.push(RightBracket);
1498 output.push(RightBracket);
1499 }
1500 } else {
1501 if chars[i] == '*' {
1502 chars.remove(i);
1503 }
1504 if is_slope {
1505 slope.push((output.len(), true, nth));
1506 }
1507 if is_area {
1508 slope.push((output.len(), false, nth));
1509 }
1510 output.push(Func(word))
1511 }
1512 } else if matches!(
1513 word.to_ascii_lowercase().as_str(),
1514 "and" | "or" | "not" | "xor" | "nand" | "implies" | "nor" | "converse"
1515 ) {
1516 if word.eq_ignore_ascii_case("not") {
1517 place_multiplier(&mut output, sumrec, &sumvar);
1518 if neg {
1519 output.push(NumStr::new(Number::from(n1.clone(), None)));
1520 output.push(InternalMultiplication);
1521 neg = false;
1522 }
1523 } else if i != 0 && chars[i - 1] == '*' {
1524 output.pop();
1525 }
1526 i += countv;
1527 if i < chars.len() && chars[i] == '*' {
1528 chars.remove(i);
1529 }
1530 match word.to_ascii_lowercase().as_str() {
1531 "and" => output.push(And),
1532 "or" => output.push(Or),
1533 "not" => output.push(Not),
1534 "xor" => output.push(Xor),
1535 "nand" => output.push(Nand),
1536 "implies" => output.push(Implies),
1537 "nor" => output.push(Nor),
1538 "converse" => output.push(Converse),
1539 _ => output.push(Func(word)),
1540 }
1541 } else if options.units
1542 && (collectvars.is_empty() || word.len() > 1)
1543 && {
1544 (unit, mul) = prefixes(word.clone(), prec.0);
1545 is_unit(&mut unit)
1546 }
1547 && var_overrule
1548 {
1549 place_multiplier(&mut output, sumrec, &sumvar);
1550 if neg {
1551 output.push(NumStr::new(Number::from(n1.clone(), None)));
1552 output.push(InternalMultiplication);
1553 neg = false;
1554 }
1555 if output.last() == Some(&Multiplication) {
1556 output.pop();
1557 output.push(InternalMultiplication)
1558 } else if matches!(
1559 output.last(),
1560 Some(Func(_)) | Some(Vector(_)) | Some(Matrix(_)) | Some(Num(_))
1561 ) {
1562 output.push(InternalMultiplication)
1563 }
1564 let (num, add) = to_unit(unit, mul, options);
1565 output.push(NumStr::new(num));
1566 if let Some(num) = add {
1567 if i > 2
1568 && ((chars[i - 2] == 't' && chars[i - 1] == 'o')
1569 || (chars[i - 2] == '-' && chars[i - 1] == '>'))
1570 {
1571 if chars[i - 3] == 'K' {
1572 output.insert(output.len().saturating_sub(2), Minus);
1573 output.insert(output.len().saturating_sub(2), NumStr::new(num));
1574 } else {
1575 output.insert(output.len().saturating_sub(3), Minus);
1576 output.insert(output.len().saturating_sub(3), NumStr::new(num));
1577 }
1578 } else {
1579 output.insert(
1580 if i != 0 && chars[i - 1].is_alphanumeric() {
1581 output.len().saturating_sub(3)
1582 } else if i != 0 && chars[i - 1] == ')' {
1583 output.len().saturating_sub(
1584 output.iter().rev().position(|c| *c == LeftBracket).unwrap(),
1585 )
1586 } else {
1587 output.len().saturating_sub(1)
1588 },
1589 LeftBracket,
1590 );
1591 output.push(Plus);
1592 output.push(NumStr::new(num));
1593 output.push(RightBracket);
1594 }
1595 }
1596 i += countv;
1597 } else if options.units && word.starts_with("to") && !output.is_empty() && var_overrule {
1598 if i != 0 && chars[i - 1] == '*' {
1599 chars.remove(i - 1);
1600 }
1601 if output.last() == Some(&Multiplication) {
1602 output.pop();
1603 }
1604 i += 1;
1605 output.push(Conversion);
1606 if chars.len() > i && (chars[i] == '*' || chars[i] == '×') {
1607 chars.remove(i);
1608 }
1609 } else {
1610 for var in vars {
1611 if var.name != vec!['e']
1612 || (options.notation != SmallEngineering
1613 || !(i != 0
1614 && i + 1 != chars.len()
1615 && chars[i - 1].is_numeric()
1616 && (chars[i + 1].is_numeric() || chars[i + 1] == '-')))
1617 {
1618 let j = i;
1619 let vn = var
1620 .name
1621 .split(|c| matches!(c, '(' | '{' | '[' | '|'))
1622 .next()
1623 .unwrap();
1624 let mut slope = 0;
1625 let mut area = 0;
1626 if i + vn.len() < chars.len() {
1627 for c in &chars[i + vn.len()..] {
1628 if *c == '\'' {
1629 slope += 1;
1630 } else if *c == '`' {
1631 area += 1;
1632 } else {
1633 break;
1634 }
1635 }
1636 }
1637 if area != 0 && slope != 0 {
1638 return Err("both ' and `");
1639 }
1640 if var.name.contains(&'(')
1641 && i + vn.len() + area + slope < chars.len()
1642 && chars[i..i + vn.len()] == *vn
1643 && matches!(chars[i + vn.len() + area + slope], '(' | '{' | '[' | '|')
1644 && !absfailed
1645 {
1646 let abs = chars[i + vn.len()] == '|';
1647 let countj = vn.len();
1648 let mut count = 0;
1649 let mut abstest = false;
1650 for (f, c) in chars[i..].iter().enumerate() {
1651 if abs && *c == '|' && (count == 0 || (abstest && count == 1)) {
1652 if abstest {
1653 abstest = false;
1654 i += f;
1655 break;
1656 }
1657 count += 1;
1658 abstest = true
1659 } else if matches!(c, '(' | '{' | '[') {
1660 count += 1;
1661 } else if matches!(c, ')' | '}' | ']') {
1662 count -= 1;
1663 if count == 0 {
1664 i += f;
1665 break;
1666 }
1667 }
1668 }
1669 if abstest {
1670 i = j;
1671 funcfailed = true;
1672 absfailed = true;
1673 continue 'main;
1674 }
1675 if i == j {
1676 i = chars.len().saturating_sub(1)
1677 }
1678 if blacklist == var.name && piecewise == 0 {
1679 if collectvars.is_empty() {
1680 return Err("recursive");
1681 }
1682 } else {
1683 count = 0;
1684 let mut ccount = 0;
1685 for c in &chars[j..i] {
1686 if *c == ','
1687 && count
1688 == if matches!(chars[j + 1], '{' | '[') {
1689 0
1690 } else {
1691 1
1692 }
1693 {
1694 ccount += 1;
1695 } else if abs
1696 && *c == '|'
1697 && (count == 0 || (abstest && count == 1))
1698 {
1699 if abstest {
1700 abstest = false;
1701 count -= 1;
1702 continue;
1703 }
1704 count += 1;
1705 abstest = true
1706 } else if matches!(c, '(' | '{' | '[') {
1707 count += 1;
1708 } else if matches!(c, ')' | '}' | ']') {
1709 count -= 1;
1710 }
1711 }
1712 if ccount != var.name.iter().filter(|c| c == &&',').count()
1713 && (!is_area || ccount != 1)
1714 {
1715 i = j;
1716 continue;
1717 }
1718 if blacklist == var.name && piecewise != 0 {
1719 output.push(Func(
1720 "@".to_owned() + &var.name.iter().collect::<String>(),
1721 ));
1722 i = j + var.name.split(|c| c == &'(').next().unwrap().len();
1723 continue 'main;
1724 }
1725 if (is_area && ccount == 1)
1726 || var.name.contains(&',') && chars.len() > 4
1727 {
1728 place_multiplier(&mut output, sumrec, &sumvar);
1729 if neg {
1730 output.push(NumStr::new(Number::from(n1.clone(), None)));
1731 output.push(InternalMultiplication);
1732 neg = false;
1733 }
1734 let nobrackets = i + 1 != chars.len()
1735 && j != 0
1736 && chars[j - 1] == ','
1737 && chars[i + 1] == ',';
1738 if !nobrackets {
1739 output.push(LeftBracket);
1740 }
1741 let mut temp = &chars[j + countj + 1 + area + slope..=i];
1742 if temp.ends_with(&[')']) {
1743 temp = &temp[..temp.len().saturating_sub(1)];
1744 }
1745 let mut commas = Vec::new();
1746 count = 0;
1747 for (f, c) in temp.iter().enumerate() {
1748 if matches!(c, '(' | '{' | '[') {
1749 count += 1;
1750 } else if matches!(c, ')' | '}' | ']') {
1751 count -= 1;
1752 } else if c == &',' && count == 0 {
1753 commas.push(f);
1754 }
1755 }
1756 let mut start = 0;
1757 let mut split = Vec::new();
1758 for end in commas {
1759 split.push(&temp[start..end]);
1760 start = end + 1;
1761 }
1762 split.push(&temp[start..]);
1763 let mut func_vars: Vec<String> = Vec::new();
1764 start = 0;
1765 for (f, c) in var.name.iter().enumerate() {
1766 if matches!(c, '(' | '{' | '[') {
1767 if count == 0 {
1768 start = f + 1;
1769 }
1770 count += 1;
1771 } else if matches!(c, ')' | '}' | ']') {
1772 count -= 1;
1773 if count == 0 {
1774 func_vars.push(var.name[start..f].iter().collect());
1775 }
1776 } else if c == &',' && count == 1 {
1777 func_vars.push(var.name[start..f].iter().collect());
1778 start = f + 1;
1779 }
1780 }
1781 while func_vars.len() < split.len() {
1782 func_vars.push(format!("@P@{}n@", func_vars.len()));
1783 }
1784 let mut parsed = var.parsed.clone();
1785 let mut fvs = var.funcvars.clone();
1786 let mut tempf = Vec::new();
1787 let mut tempf2 = Vec::new();
1788 let mut ignore: Vec<usize> = Vec::new();
1789 let mut ignorefv: Vec<(usize, usize)> = Vec::new();
1790 for (z, (varf, func_var)) in split.iter().zip(func_vars).enumerate()
1791 {
1792 let rnum = if let Ok(n) = Complex::parse_radix(
1793 varf.iter().collect::<String>(),
1794 options.base.0,
1795 ) {
1796 NumStr::new(Number::from(n.complete(prec), None))
1797 } else {
1798 let parsed;
1799 let exit;
1800 let func;
1801 let tempgraph;
1802 let sum_var;
1803 let mut cv = collectvars.clone();
1804 if !cv.is_empty() {
1805 if cv[0].0 < 0 {
1806 cv[0].0 -= 1;
1807 } else {
1808 cv[0].0 = -1
1809 }
1810 }
1811 (parsed, func, tempgraph, exit, sum_var) = match input_var(
1812 &varf.iter().collect::<String>(),
1813 vars,
1814 sumrec,
1815 bracket,
1816 options,
1817 print,
1818 depth + 1,
1819 blacklist.clone(),
1820 false,
1821 &mut cv,
1822 Some(solvesn),
1823 Some(ison),
1824 ) {
1825 Ok(f) => f,
1826 Err(s) => {
1827 err = s;
1828 continue;
1829 }
1830 };
1831 if tempgraph.graph {
1832 graph.graph = true
1833 }
1834 if tempgraph.x {
1835 graph.x = true
1836 }
1837 if tempgraph.y {
1838 graph.y = true
1839 }
1840 if exit {
1841 return Ok((
1842 Vec::new(),
1843 Vec::new(),
1844 HowGraphing::default(),
1845 true,
1846 None,
1847 ));
1848 }
1849 if let Some(s) = sum_var {
1850 if collectvars.is_empty() {
1851 if s != "x" && sumvar == Some("x".to_string()) {
1852 graph.graph = true;
1853 graph.x = true;
1854 sumvar = Some(s.clone());
1855 } else if s != "y"
1856 && s != "x"
1857 && sumvar == Some("y".to_string())
1858 {
1859 graph.graph = true;
1860 graph.y = true;
1861 sumvar = Some(s.clone());
1862 } else if s != "y"
1863 && s != "x"
1864 && s != "w"
1865 && sumvar == Some("w".to_string())
1866 {
1867 graph.graph = true;
1868 graph.w = true;
1869 sumvar = Some(s.clone());
1870 } else if !(s == "x" || s == "y" || s == "w")
1871 || sumvar.is_none()
1872 || sumvar == Some("y".to_string())
1873 || sumvar == Some("x".to_string())
1874 || sumvar == Some("w".to_string())
1875 {
1876 sumvar = Some(s.clone());
1877 } else if s == "y" {
1878 graph.graph = true;
1879 graph.y = true;
1880 } else if s == "x" {
1881 graph.graph = true;
1882 graph.x = true;
1883 } else if s == "w" {
1884 graph.graph = true;
1885 graph.w = true;
1886 }
1887 } else if collectvars[0].0 < 0 {
1888 sumvar = Some(s)
1889 } else {
1890 output.insert(collectvars[0].1, Comma);
1891 output.insert(collectvars[0].1, Func(s.clone()));
1892 collectvars.remove(0);
1893 }
1894 }
1895 if (tempgraph.graph && parsed.len() > 1)
1896 || print
1897 || sumrec.iter().any(|c| c.0 == -1)
1898 || parsed.iter().any(|c| {
1899 if let Func(s) = c {
1900 sumrec.iter().any(|r| &r.1 == s)
1901 || sumvar.clone() == Some(s.clone())
1902 || matches!(
1903 s.as_str(),
1904 "x" | "y"
1905 | "w"
1906 | "rnd"
1907 | "rand"
1908 | "epoch"
1909 | "roll"
1910 )
1911 || s.starts_with("rand_")
1912 } else {
1913 false
1914 }
1915 })
1916 || func.iter().any(|c| {
1917 c.1.iter().any(|c| {
1918 if let Func(s) = c {
1919 sumrec.iter().any(|r| &r.1 == s)
1920 || sumvar.clone() == Some(s.clone())
1921 || matches!(
1922 s.as_str(),
1923 "x" | "y"
1924 | "w"
1925 | "rnd"
1926 | "rand"
1927 | "epoch"
1928 | "roll"
1929 )
1930 || s.starts_with("rand_")
1931 } else {
1932 false
1933 }
1934 })
1935 })
1936 {
1937 if parsed.len() == 1 {
1938 parsed.into_iter().next().unwrap()
1939 } else {
1940 let iden = format!(
1941 "@{}{}{}{}@",
1942 i,
1943 func_var,
1944 depth,
1945 vars.len()
1946 );
1947 funcvars.extend(func);
1948 funcvars.push((iden.clone(), parsed));
1949 Func(iden)
1950 }
1951 } else {
1952 match do_math(parsed, options, func) {
1953 Ok(f) => f,
1954 Err(s) => {
1955 err = s;
1956 continue;
1957 }
1958 }
1959 }
1960 };
1961 let mut num = vec![rnum];
1962 if print
1963 && if let Num(n) = &num[0] {
1964 n.number.real().is_sign_negative()
1965 } else {
1966 false
1967 }
1968 {
1969 num.insert(0, LeftBracket);
1970 num.push(RightBracket);
1971 }
1972 if z == 0 && (area != 0 || slope != 0) {
1973 tempf = num;
1974 if area != 0 {
1975 output.push(Func("area".to_string()));
1976 } else {
1977 output.push(Func("slope".to_string()));
1978 }
1979 output.push(LeftBracket);
1980 output.push(Func("@p".to_string() + &i.to_string()));
1981 output.push(Comma);
1982 num = vec![Func("@p".to_string() + &i.to_string())]
1983 } else if z == 1
1984 && area != 0
1985 && ccount == 1
1986 && !var.name.contains(&',')
1987 {
1988 tempf2 = num.clone();
1989 }
1990 let mut k = 0;
1991 for (x, fv) in fvs.clone().iter().enumerate() {
1992 if !fv.0.ends_with(')') {
1993 k = fv.1.len();
1994 while k != 0 {
1995 k -= 1;
1996 if fv.1[k].str_is(&func_var)
1997 && !ignorefv.contains(&(x, k))
1998 {
1999 if num.len() == 1 {
2000 ignorefv.push((x, k));
2001 fvs[x].1[k] = num[0].clone();
2002 } else {
2003 ignorefv.push((x, k + 1));
2004 fvs[x].1.remove(k);
2005 fvs[x].1.splice(k..k, num.clone());
2006 }
2007 }
2008 }
2009 }
2010 }
2011 while k < parsed.len() {
2012 if parsed[k].str_is(&func_var) && !ignore.contains(&k) {
2013 if num.len() == 1 {
2014 ignore.push(k);
2015 parsed[k] = num[0].clone();
2016 } else {
2017 parsed.remove(k);
2018 ignore.push(k + 1);
2019 parsed.splice(k..k, num.clone());
2020 k += num.len();
2021 continue;
2022 }
2023 }
2024 k += 1;
2025 }
2026 }
2027 let mut k = 0;
2028 while k < parsed.len() {
2029 for fv in &fvs {
2030 if parsed[k].str_is(&fv.0) {
2031 if !fv.0.ends_with(')') {
2032 parsed[k] =
2033 Func(format!("@{}@{}{}", i, depth, fv.0));
2034 } else if !fv.0.starts_with('@') {
2035 parsed[k] = Func(format!("@{}", fv.0));
2036 }
2037 }
2038 }
2039 k += 1;
2040 }
2041 for (x, fv) in fvs.clone().iter().enumerate() {
2042 k = fv.1.len();
2043 while k != 0 {
2044 k -= 1;
2045 for fc in fvs.clone() {
2046 if let Func(s) = &fv.1[k] {
2047 if s == &fc.0 && s != &fv.0 {
2048 if !fc.0.contains('(') {
2049 fvs[x].1[k] = Func(format!(
2050 "@{}@{}{}",
2051 i, depth, fc.0
2052 ))
2053 } else if !fc.0.starts_with('@') {
2054 fvs[x].1[k] = Func(format!("@{}", fc.0))
2055 }
2056 }
2057 }
2058 }
2059 }
2060 }
2061 for (x, fv) in fvs.clone().iter().enumerate() {
2062 if !fv.0.ends_with(')') {
2063 fvs[x].0 = format!("@{}@{}{}", i, depth, fv.0);
2064 } else if !fv.0.starts_with('@') {
2065 fvs[x].0 = format!("@{}", fv.0);
2066 }
2067 }
2068 funcvars.extend(fvs);
2069 output.extend(parsed);
2070 if area != 0 || slope != 0 {
2071 if area != 0 && var.name.contains(&',') {
2072 output.push(Comma);
2073 output.push(NumStr::new(Number::from(
2074 Complex::new(options.prec),
2075 None,
2076 )))
2077 }
2078 output.push(Comma);
2079 output.extend(tempf);
2080 if area != 0 && ccount == 1 && !var.name.contains(&',') {
2081 output.push(Comma);
2082 output.extend(tempf2);
2083 }
2084 if area + slope != 1 {
2085 output.push(Comma);
2086 output.push(NumStr::new(Number::from(
2087 Complex::with_val(options.prec, area + slope),
2088 None,
2089 )))
2090 }
2091 output.push(RightBracket);
2092 }
2093 if pwr.1 == *bracket + 1 {
2094 for _ in 0..pwr.2 {
2095 output.push(RightBracket);
2096 }
2097 pwr = (false, 0, 0);
2098 }
2099 if !subfact.is_empty() && subfact[0] == *bracket + 1 {
2100 subfact.remove(0);
2101 output.push(RightBracket);
2102 output.push(RightBracket);
2103 }
2104 if !nobrackets {
2105 output.push(RightBracket);
2106 }
2107 if !exp.0.is_empty() && exp.1 == *bracket {
2108 output.push(Exponent);
2109 output.push(NumStr::new(Number::from(
2110 match Complex::parse_radix(exp.0.as_bytes(), options.base.0)
2111 {
2112 Ok(n) => n.complete(prec),
2113 _ => return Err("exponent error"),
2114 },
2115 None,
2116 )));
2117 exp = (String::new(), 0);
2118 }
2119 i += 1;
2120 continue 'main;
2121 } else {
2122 place_multiplier(&mut output, sumrec, &sumvar);
2123 if neg {
2124 output.push(NumStr::new(Number::from(n1.clone(), None)));
2125 output.push(InternalMultiplication);
2126 neg = false;
2127 }
2128 let nobrackets = j != 0
2129 && chars[j - 1] == ','
2130 && i + 1 != chars.len()
2131 && chars[i + 1] == ',';
2132 if !nobrackets {
2133 output.push(LeftBracket);
2134 }
2135 let mut temp = &chars[j + countj + 1..=i];
2136 if temp.ends_with(&[')']) {
2137 temp = &temp[..temp.len().saturating_sub(1)];
2138 }
2139 let l = var.name[var.name.iter().position(|c| c == &'(').unwrap()
2140 + 1
2141 ..var.name.len().saturating_sub(1)]
2142 .iter()
2143 .collect::<String>();
2144 let mut parsed = var.parsed.clone();
2145 let mut fvs = var.funcvars.clone();
2146 let mut k = 0;
2147 let mut num = if let Ok(n) = Complex::parse_radix(
2148 temp.iter().collect::<String>(),
2149 options.base.0,
2150 ) {
2151 vec![NumStr::new(Number::from(n.complete(prec), None))]
2152 } else {
2153 let parsed;
2154 let exit;
2155 let func;
2156 let tempgraph;
2157 let sum_var;
2158 let mut cv = collectvars.clone();
2159 if !cv.is_empty() {
2160 if cv[0].0 < 0 {
2161 cv[0].0 -= 1;
2162 } else {
2163 cv[0].0 = -1
2164 }
2165 }
2166 (parsed, func, tempgraph, exit, sum_var) = match input_var(
2167 &temp.iter().collect::<String>(),
2168 vars,
2169 sumrec,
2170 bracket,
2171 options,
2172 print,
2173 depth + 1,
2174 blacklist.clone(),
2175 false,
2176 &mut cv,
2177 Some(solvesn),
2178 Some(ison),
2179 ) {
2180 Ok(f) => f,
2181 Err(s) => {
2182 err = s;
2183 continue;
2184 }
2185 };
2186 if tempgraph.graph {
2187 graph.graph = true
2188 }
2189 if tempgraph.x {
2190 graph.x = true
2191 }
2192 if tempgraph.y {
2193 graph.y = true
2194 }
2195 if exit {
2196 return Ok((
2197 Vec::new(),
2198 Vec::new(),
2199 HowGraphing::default(),
2200 true,
2201 None,
2202 ));
2203 }
2204 if let Some(mut s) = sum_var {
2205 if collectvars.is_empty() {
2206 if s.ends_with('i') {
2207 s.pop();
2208 }
2209 if s != "x" && sumvar == Some("x".to_string()) {
2210 graph.graph = true;
2211 graph.x = true;
2212 sumvar = Some(s.clone());
2213 } else if s != "y"
2214 && s != "x"
2215 && sumvar == Some("y".to_string())
2216 {
2217 graph.graph = true;
2218 graph.y = true;
2219 sumvar = Some(s.clone());
2220 } else if s != "y"
2221 && s != "x"
2222 && s != "w"
2223 && sumvar == Some("w".to_string())
2224 {
2225 graph.graph = true;
2226 graph.w = true;
2227 sumvar = Some(s.clone());
2228 } else if !(s == "x" || s == "y" || s == "w")
2229 || sumvar.is_none()
2230 || sumvar == Some("y".to_string())
2231 || sumvar == Some("x".to_string())
2232 || sumvar == Some("w".to_string())
2233 {
2234 sumvar = Some(s.clone());
2235 } else if s == "y" {
2236 graph.graph = true;
2237 graph.y = true;
2238 } else if s == "x" {
2239 graph.graph = true;
2240 graph.x = true;
2241 } else if s == "w" {
2242 graph.graph = true;
2243 graph.w = true;
2244 }
2245 } else if collectvars[0].0 < 0 {
2246 sumvar = Some(s)
2247 } else {
2248 output.insert(collectvars[0].1, Comma);
2249 output.insert(collectvars[0].1, Func(s.clone()));
2250 collectvars.remove(0);
2251 }
2252 }
2253 if (tempgraph.graph && parsed.len() > 1)
2254 || print
2255 || sumrec.iter().any(|c| c.0 == -1)
2256 || parsed.iter().any(|c| {
2257 if let Func(s) = c {
2258 sumrec.iter().any(|r| &r.1 == s)
2259 || sumvar.clone() == Some(s.clone())
2260 || matches!(
2261 s.as_str(),
2262 "x" | "y"
2263 | "w"
2264 | "rnd"
2265 | "rand"
2266 | "epoch"
2267 | "roll"
2268 )
2269 || s.starts_with("rand_")
2270 } else {
2271 false
2272 }
2273 })
2274 || func.iter().any(|c| {
2275 c.1.iter().any(|c| {
2276 if let Func(s) = c {
2277 sumrec.iter().any(|r| &r.1 == s)
2278 || sumvar.clone() == Some(s.clone())
2279 || matches!(
2280 s.as_str(),
2281 "x" | "y"
2282 | "w"
2283 | "rnd"
2284 | "rand"
2285 | "epoch"
2286 | "roll"
2287 )
2288 || s.starts_with("rand_")
2289 } else {
2290 false
2291 }
2292 })
2293 })
2294 {
2295 let iden = format!("@{}{}{}{}@", i, l, depth, vars.len());
2296 if parsed.len() == 1
2297 && if let Func(s) = &parsed[0] {
2298 !matches!(s.as_str(), "rnd" | "rand" | "epoch")
2299 } else {
2300 true
2301 }
2302 {
2303 parsed
2304 } else {
2305 funcvars.extend(func);
2306 funcvars.push((iden.clone(), parsed));
2307 vec![Func(iden)]
2308 }
2309 } else {
2310 vec![match do_math(parsed, options, func) {
2311 Ok(f) => f,
2312 Err(s) => {
2313 err = s;
2314 continue;
2315 }
2316 }]
2317 }
2318 };
2319 if abs {
2320 num.insert(0, LeftBracket);
2321 num.insert(0, Func("norm".to_string()));
2322 num.insert(0, LeftBracket);
2323 num.push(RightBracket);
2324 num.push(RightBracket)
2325 }
2326 if print
2327 && num.len() == 1
2328 && if let Num(n) = num[0].clone() {
2329 n.number.real().is_sign_negative()
2330 } else {
2331 false
2332 }
2333 {
2334 num.insert(0, LeftBracket);
2335 num.push(RightBracket);
2336 }
2337 let mut tempf = Vec::new();
2338 if area != 0 || slope != 0 {
2339 tempf = num;
2340 if area != 0 {
2341 output.push(Func("area".to_string()));
2342 } else {
2343 output.push(Func("slope".to_string()));
2344 }
2345 output.push(LeftBracket);
2346 output.push(Func("@p".to_string() + &i.to_string()));
2347 output.push(Comma);
2348 num = vec![Func("@p".to_string() + &i.to_string())]
2349 }
2350 while k < parsed.len() {
2351 if parsed[k].str_is(&l) {
2352 parsed.remove(k);
2353 if num.len() == 1 {
2354 parsed.insert(k, num[0].clone());
2355 } else {
2356 parsed.splice(k..k, num.clone());
2357 k += num.len();
2358 continue;
2359 }
2360 }
2361 k += 1;
2362 }
2363 for fv in fvs.iter_mut() {
2364 if !fv.0.ends_with(')') {
2365 k = fv.1.len();
2366 while k != 0 {
2367 k -= 1;
2368 if fv.1[k].str_is(&l) {
2369 fv.1.remove(k);
2370 if num.len() == 1 {
2371 fv.1.insert(k, num[0].clone());
2372 } else {
2373 fv.1.splice(k..k, num.clone());
2374 }
2375 }
2376 }
2377 }
2378 }
2379 let mut k = 0;
2380 while k < parsed.len() {
2381 for fv in &fvs {
2382 if parsed[k].str_is(&fv.0) {
2383 if !fv.0.ends_with(')') {
2384 parsed[k] =
2385 Func(format!("@{}@{}{}", i, depth, fv.0));
2386 } else if !fv.0.starts_with('@') {
2387 parsed[k] = Func(format!("@{}", fv.0));
2388 }
2389 }
2390 }
2391 k += 1;
2392 }
2393 for (x, fv) in fvs.clone().iter().enumerate() {
2394 k = fv.1.len();
2395 while k != 0 {
2396 k -= 1;
2397 for fc in fvs.clone() {
2398 if let Func(s) = &fv.1[k] {
2399 if s == &fc.0 && s != &fv.0 {
2400 if !fc.0.contains('(') {
2401 fvs[x].1[k] = Func(format!(
2402 "@{}@{}{}",
2403 i, depth, fc.0
2404 ))
2405 } else if !fc.0.starts_with('@') {
2406 fvs[x].1[k] = Func(format!("@{}", fc.0))
2407 }
2408 }
2409 }
2410 }
2411 }
2412 }
2413 for (x, fv) in fvs.clone().iter().enumerate() {
2414 if !fv.0.ends_with(')') {
2415 fvs[x].0 = format!("@{}@{}{}", i, depth, fv.0);
2416 } else if !fv.0.starts_with('@') {
2417 fvs[x].0 = format!("@{}", fv.0);
2418 }
2419 }
2420 funcvars.extend(fvs);
2421 output.extend(parsed);
2422 if area != 0 || slope != 0 {
2423 if area != 0 {
2424 output.push(Comma);
2425 output.push(NumStr::new(Number::from(
2426 Complex::new(options.prec),
2427 None,
2428 )))
2429 }
2430 output.push(Comma);
2431 output.extend(tempf);
2432 if area + slope != 1 {
2433 output.push(Comma);
2434 output.push(NumStr::new(Number::from(
2435 Complex::with_val(options.prec, area + slope),
2436 None,
2437 )))
2438 }
2439 output.push(RightBracket);
2440 }
2441 if pwr.1 == *bracket + 1 {
2442 for _ in 0..pwr.2 {
2443 output.push(RightBracket);
2444 }
2445 pwr = (false, 0, 0);
2446 }
2447 if !subfact.is_empty() && subfact[0] == *bracket + 1 {
2448 subfact.remove(0);
2449 output.push(RightBracket);
2450 output.push(RightBracket);
2451 }
2452 if !nobrackets {
2453 output.push(RightBracket);
2454 }
2455 if !exp.0.is_empty() && exp.1 == *bracket {
2456 output.push(Exponent);
2457 output.push(NumStr::new(Number::from(
2458 match Complex::parse_radix(exp.0.as_bytes(), options.base.0)
2459 {
2460 Ok(n) => n.complete(prec),
2461 _ => return Err("exponent error"),
2462 },
2463 None,
2464 )));
2465 exp = (String::new(), 0);
2466 }
2467 i += 1;
2468 continue 'main;
2469 }
2470 }
2471 } else if i + var.name.len() <= chars.len()
2472 && (chars[i..i + var.name.len()] == var.name
2473 || (wordv != chars[i..i + var.name.len()].iter().collect::<String>()
2474 && wordv.starts_with(&var.name.iter().collect::<String>())))
2475 {
2476 if blacklist == var.name {
2477 if collectvars.is_empty() {
2478 return Err("recursive");
2479 }
2480 } else {
2481 i += if chars[i..i + var.name.len()].contains(&'@')
2482 && !var.name.contains(&'@')
2483 {
2484 let mut count = 0;
2485 let mut countw = 0;
2486 let mut depth = false;
2487 let mut word = String::new();
2488 for c in chars[i..].iter() {
2489 if word == var.name.iter().collect::<String>() {
2490 if depth {
2491 count += chars[i + count..]
2492 .iter()
2493 .position(|a| a == &'@')
2494 .unwrap()
2495 + 1;
2496 }
2497 break;
2498 }
2499 if c == &'@' {
2500 depth = !depth;
2501 } else if c == &var.name[countw] {
2502 word.push(*c);
2503 countw += 1;
2504 } else if !depth {
2505 i += 1;
2506 continue 'main;
2507 }
2508 count += 1;
2509 }
2510 count
2511 } else {
2512 var.name.len()
2513 };
2514 place_multiplier(&mut output, sumrec, &sumvar);
2515 if neg {
2516 output.push(NumStr::new(Number::from(n1.clone(), None)));
2517 output.push(InternalMultiplication);
2518 neg = false;
2519 }
2520 let print = print
2521 && if let Num(n) = var.parsed[0].clone() {
2522 n.number.real().is_sign_negative()
2523 } else {
2524 false
2525 };
2526 if print {
2527 output.push(LeftBracket);
2528 }
2529 if !var.parsed.is_empty() {
2530 output.push(var.parsed[0].clone());
2531 } else {
2532 return Err("bad input2");
2533 }
2534 if print {
2535 output.push(RightBracket);
2536 }
2537 if scientific {
2538 output.push(RightBracket);
2539 scientific = false;
2540 }
2541 if pwr.0
2542 && pwr.1 == *bracket
2543 && (chars.len() <= i + 1 || chars[i + 1] != '^')
2544 {
2545 for _ in 0..pwr.2 {
2546 output.push(RightBracket);
2547 }
2548 pwr.0 = false;
2549 pwr.2 = 0
2550 }
2551 if !subfact.is_empty() && subfact[0] == 0 {
2552 subfact.remove(0);
2553 output.push(RightBracket);
2554 output.push(RightBracket);
2555 }
2556 continue 'main;
2557 }
2558 }
2559 }
2560 }
2561 if (i == 0 || chars[i - 1] != ' ' || c != ' ')
2562 && (if options.notation == SmallEngineering {
2563 matches!(c, 'x' | 'y' | 'w' | 'z' | 'i' | 'e')
2564 } else {
2565 matches!(c, 'x' | 'y' | 'w' | 'z' | 'i' | 'E')
2566 } || !c.is_alphabetic())
2567 && ((solvesn == 0 && ison == 0) || c == 'i' || {
2568 let a = chars[i..]
2569 .iter()
2570 .filter(|a| matches!(a, '(' | ')' | '~' | '='))
2571 .cloned()
2572 .collect::<Vec<char>>();
2573 a.starts_with(&['(']) && a.ends_with(&[')'])
2574 })
2575 {
2576 if neg {
2577 output.push(NumStr::new(Number::from(n1.clone(), None)));
2578 output.push(InternalMultiplication);
2579 neg = false;
2580 }
2581 match c {
2582 'ⁱ' => pow.push('i'),
2583 'E' | 'e'
2584 if (options.notation == SmallEngineering && c == 'e')
2585 || (options.notation != SmallEngineering && c == 'E') =>
2586 {
2587 if let Some(last) = output.last() {
2588 if last.num().is_ok()
2589 || last.str_is("x")
2590 || last.str_is("y")
2591 || last.str_is("w")
2592 {
2593 output.insert(output.len().saturating_sub(1), LeftBracket);
2594 if i + 1 != chars.len()
2595 && (matches!(
2596 chars[i + 1],
2597 '-' | '+' | 'x' | 'y' | 'w' | 'z' | 'i'
2598 ) || is_digit(chars[i + 1], options.base.0))
2599 {
2600 scientific = true;
2601 }
2602 }
2603 }
2604 place_multiplier(&mut output, sumrec, &sumvar);
2605 output.push(NumStr::new(Number::from(
2606 Complex::with_val(options.prec, options.base.0),
2607 None,
2608 )));
2609 if i + 1 != chars.len()
2610 && (chars[i + 1].is_alphanumeric()
2611 || is_digit(chars[i + 1], options.base.0)
2612 || matches!(chars[i + 1], '-' | '+' | '(' | '{' | '|'))
2613 {
2614 output.push(Exponent);
2615 }
2616 if !(i + 1 != chars.len()
2617 && (matches!(chars[i + 1], '-' | '+' | 'x' | 'y' | 'w' | 'z' | 'i')
2618 || is_digit(chars[i + 1], options.base.0)))
2619 {
2620 output.push(RightBracket);
2621 }
2622 }
2623 'x' | 'y' | 'w'
2624 if collectvars.is_empty() && options.graphtype != GraphType::None =>
2625 {
2626 graph.graph = true;
2627 if c == 'x' {
2628 graph.x = true
2629 }
2630 if c == 'y' {
2631 graph.y = true
2632 }
2633 if c == 'y' {
2634 graph.w = true
2635 }
2636 place_multiplier(&mut output, sumrec, &sumvar);
2637 output.push(Func(c.to_string()));
2638 if scientific {
2639 output.push(RightBracket);
2640 scientific = false;
2641 }
2642 if pwr.0
2643 && pwr.1 == *bracket
2644 && (chars.len() <= i + 1 || chars[i + 1] != '^')
2645 {
2646 for _ in 0..pwr.2 {
2647 output.push(RightBracket);
2648 }
2649 pwr.0 = false;
2650 pwr.2 = 0
2651 }
2652 if !subfact.is_empty() && subfact[0] == 0 {
2653 subfact.remove(0);
2654 output.push(RightBracket);
2655 output.push(RightBracket);
2656 }
2657 }
2658 'i' => {
2659 place_multiplier(&mut output, sumrec, &sumvar);
2660 output.push(NumStr::new(Number::from(
2661 Complex::with_val(options.prec, (0, 1)),
2662 None,
2663 )));
2664 if pwr.0
2665 && pwr.1 == *bracket
2666 && (chars.len() <= i + 1 || chars[i + 1] != '^')
2667 {
2668 for _ in 0..pwr.2 {
2669 output.push(RightBracket);
2670 }
2671 pwr.0 = false;
2672 pwr.2 = 0
2673 }
2674 if scientific {
2675 output.push(RightBracket);
2676 scientific = false;
2677 }
2678 if !subfact.is_empty() && subfact[0] == 0 {
2679 subfact.remove(0);
2680 output.push(RightBracket);
2681 output.push(RightBracket);
2682 }
2683 }
2684 'z' if collectvars.is_empty() && options.graphtype != GraphType::None => {
2685 graph.graph = true;
2686 graph.x = true;
2687 graph.y = true;
2688 place_multiplier(&mut output, sumrec, &sumvar);
2689 output.push(LeftBracket);
2690 output.push(Func('x'.to_string()));
2691 output.push(Plus);
2692 output.push(Func('y'.to_string()));
2693 output.push(Multiplication);
2694 output.push(NumStr::new(Number::from(
2695 Complex::with_val(options.prec, (0, 1)),
2696 None,
2697 )));
2698 output.push(RightBracket);
2699 if scientific {
2700 output.push(RightBracket);
2701 scientific = false;
2702 }
2703 if pwr.0
2704 && pwr.1 == *bracket
2705 && (chars.len() <= i + 1 || chars[i + 1] != '^')
2706 {
2707 for _ in 0..pwr.2 {
2708 output.push(RightBracket);
2709 }
2710 pwr.0 = false;
2711 pwr.2 = 0
2712 }
2713 if !subfact.is_empty() && subfact[0] == 0 {
2714 subfact.remove(0);
2715 output.push(RightBracket);
2716 output.push(RightBracket);
2717 }
2718 }
2719 _ => {
2720 if !collectvars.is_empty() {
2721 if neg {
2722 output.push(NumStr::new(Number::from(n1.clone(), None)));
2723 output.push(InternalMultiplication);
2724 neg = false;
2725 }
2726 sumrec.push((collectvars[0].0, wordv.clone()));
2727 if collectvars[0].0 < 0 {
2728 sumvar = Some(wordv.clone());
2729 } else {
2730 output.insert(collectvars[0].1, Comma);
2731 output.insert(collectvars[0].1, Func(wordv.clone()));
2732 }
2733 place_multiplier(&mut output, sumrec, &sumvar);
2734 output.push(Func(wordv));
2735 collectvars.remove(0);
2736 if pwr.0
2737 && pwr.1 == *bracket
2738 && (chars.len() <= i + 1 || chars[i + 1] != '^')
2739 {
2740 for _ in 0..pwr.2 {
2741 output.push(RightBracket);
2742 }
2743 pwr.0 = false;
2744 pwr.2 = 0
2745 }
2746 if scientific {
2747 output.push(RightBracket);
2748 scientific = false;
2749 }
2750 if !subfact.is_empty() && subfact[0] == 0 {
2751 subfact.remove(0);
2752 output.push(RightBracket);
2753 output.push(RightBracket);
2754 }
2755 }
2756 }
2757 }
2758 } else if !collectvars.is_empty() || solvesn != 0 || ison != 0 {
2759 if neg {
2760 output.push(NumStr::new(Number::from(n1.clone(), None)));
2761 output.push(InternalMultiplication);
2762 neg = false;
2763 }
2764 if !collectvars.is_empty() {
2765 sumrec.push((collectvars[0].0, word.clone()));
2766 if collectvars[0].0 < 0 {
2767 sumvar = Some(word.clone());
2768 } else {
2769 output.insert(collectvars[0].1, Comma);
2770 output.insert(collectvars[0].1, Func(word.clone()));
2771 }
2772 collectvars.remove(0);
2773 } else {
2774 if word.is_empty() {
2775 word = wordv;
2776 }
2777 if word.ends_with('i') {
2778 word.pop();
2779 }
2780 if word != "x" && sumvar == Some("x".to_string()) {
2781 graph.graph = true;
2782 graph.x = true;
2783 sumvar = Some(word.clone());
2784 } else if word != "y" && word != "x" && sumvar == Some("y".to_string()) {
2785 graph.graph = true;
2786 graph.y = true;
2787 sumvar = Some(word.clone());
2788 } else if word != "y"
2789 && word != "x"
2790 && word != "w"
2791 && sumvar == Some("w".to_string())
2792 {
2793 graph.graph = true;
2794 graph.w = true;
2795 sumvar = Some(word.clone());
2796 } else if !(word == "x" || word == "y" || word == "w")
2797 || sumvar.is_none()
2798 || sumvar == Some("y".to_string())
2799 || sumvar == Some("x".to_string())
2800 || sumvar == Some("w".to_string())
2801 {
2802 sumvar = Some(word.clone());
2803 } else if word == "y" {
2804 graph.graph = true;
2805 graph.y = true;
2806 } else if word == "x" {
2807 graph.graph = true;
2808 graph.x = true;
2809 } else if word == "w" {
2810 graph.graph = true;
2811 graph.w = true;
2812 }
2813 }
2814 place_multiplier(&mut output, sumrec, &sumvar);
2815 output.push(Func(word));
2816 if pwr.0 && pwr.1 == *bracket && (chars.len() <= i + 1 || chars[i + 1] != '^') {
2817 for _ in 0..pwr.2 {
2818 output.push(RightBracket);
2819 }
2820 pwr.0 = false;
2821 pwr.2 = 0
2822 }
2823 if scientific {
2824 output.push(RightBracket);
2825 scientific = false;
2826 }
2827 if !subfact.is_empty() && subfact[0] == 0 {
2828 subfact.remove(0);
2829 output.push(RightBracket);
2830 output.push(RightBracket);
2831 }
2832 } else if piecewise != 0
2833 && blacklist.contains(&'(')
2834 && blacklist
2835 .iter()
2836 .collect::<String>()
2837 .split('(')
2838 .next()
2839 .unwrap()
2840 == wordv
2841 {
2842 output.push(Func("@".to_owned() + &wordv));
2843 } else {
2844 undf = true
2845 }
2846 funcfailed = false;
2847 absfailed = false;
2848 i += 1;
2849 }
2850 }
2851 for _ in 0..pwr.2 + ceilfoor {
2852 output.push(RightBracket);
2853 }
2854 for s in solves {
2855 if s.1 == 2 {
2856 output.push(Comma);
2857 output.push(NumStr::new(Number::from(
2858 Complex::with_val(options.prec, (Nan, 1)),
2859 None,
2860 )));
2861 } else if s.1 == 1 {
2862 output.push(Comma);
2863 output.push(NumStr::new(Number::from(
2864 Complex::with_val(options.prec, Nan),
2865 None,
2866 )));
2867 }
2868 output.push(RightBracket);
2869 }
2870 for s in solvesp {
2871 if !s.2 {
2872 output.push(RightBracket);
2873 }
2874 if s.1 == 2 {
2875 output.push(Comma);
2876 output.push(NumStr::new(Number::from(
2877 Complex::with_val(options.prec, (Nan, 1)),
2878 None,
2879 )));
2880 } else if s.1 == 1 {
2881 output.push(Comma);
2882 output.push(NumStr::new(Number::from(
2883 Complex::with_val(options.prec, Nan),
2884 None,
2885 )));
2886 }
2887 output.push(RightBracket);
2888 }
2889 for _ in 0..iso.len() {
2890 output.push(RightBracket);
2891 }
2892 for s in isop {
2893 if !s.1 {
2894 output.push(RightBracket);
2895 }
2896 output.push(RightBracket);
2897 }
2898 if !pow.is_empty() {
2899 let i = pow.matches('i').count() % 4;
2900 pow = pow.replace('i', "");
2901 if pow.is_empty() {
2902 pow = "1".to_string();
2903 }
2904 match output.last() {
2905 Some(Num(_)) | Some(Vector(_)) | Some(Matrix(_)) => output.push(Exponent),
2906 Some(Func(s))
2907 if matches!(s.as_str(), "x" | "y" | "w" | "rnd" | "rand" | "epoch")
2908 || sumrec.iter().any(|v| &v.1 == s) =>
2909 {
2910 output.push(Exponent)
2911 }
2912 _ => {}
2913 }
2914 output.push(NumStr::new(Number::from(
2915 match Complex::parse_radix(pow.as_bytes(), options.base.0) {
2916 Ok(n) => n.complete(prec),
2917 _ => return Err("exponent error"),
2918 } * pow_nth(
2919 Complex::with_val(options.prec, (0, 1)),
2920 Complex::with_val(options.prec, i),
2921 ),
2922 None,
2923 )));
2924 }
2925 if !exp.0.is_empty() {
2926 output.push(Exponent);
2927 output.push(NumStr::new(Number::from(
2928 match Complex::parse_radix(exp.0.as_bytes(), options.base.0) {
2929 Ok(n) => n.complete(prec),
2930 _ => return Err("exponent error"),
2931 },
2932 None,
2933 )));
2934 }
2935 if neg {
2936 output.push(NumStr::new(Number::from(n1, None)));
2937 }
2938 for _ in abs {
2939 output.push(RightBracket);
2940 output.push(RightBracket);
2941 }
2942 let mut count = 0;
2943 i = 0;
2944 let mut double: Vec<(usize, isize)> = Vec::new();
2945 let mut brackets = Vec::new();
2946 for n in slope.iter().rev() {
2947 let nth = n.2;
2948 let slope = n.1;
2949 let n = n.0;
2950 output.insert(n, Comma);
2951 output.insert(n, Func("@p".to_string() + &n.to_string()));
2952 output.insert(n, LeftBracket);
2953 if slope {
2954 output.insert(n, Func("slope".to_string()));
2955 } else {
2956 output.insert(n, Func("area".to_string()));
2957 }
2958 let mut bracket = 0;
2959 let mut last = 0;
2960 let mut end = 0;
2961 if n + 6 > output.len() {
2962 break;
2963 }
2964 if !matches!(output[n + 5], LeftBracket | LeftCurlyBracket) {
2965 output.insert(n + 5, LeftBracket);
2966 output.insert(n + 7, RightBracket);
2967 }
2968 let mut start_to_end = false;
2969 for (k, j) in output[n + 6..].iter().enumerate() {
2970 match j {
2971 LeftBracket | LeftCurlyBracket => {
2972 bracket += 1;
2973 }
2974 RightBracket | RightCurlyBracket => {
2975 if bracket == 0 {
2976 if end == 0 {
2977 end = k;
2978 }
2979 last = k + 2;
2980 break;
2981 }
2982 bracket -= 1;
2983 }
2984 Comma if bracket == 0 && end == 0 => {
2985 if slope {
2986 end = k
2987 } else {
2988 start_to_end = true
2989 }
2990 }
2991 _ => {}
2992 }
2993 }
2994 let arg = output.drain(n + 6..n + 6 + end).collect::<Vec<NumStr>>();
2995 output.insert(n + 6, Func("@p".to_string() + &n.to_string()));
2996 output.insert(n + 6 + last - end, RightBracket);
2997 if nth != 1 {
2998 output.insert(
2999 n + 6 + last - end,
3000 NumStr::new(Number::from(Complex::with_val(options.prec, nth), None)),
3001 );
3002 output.insert(n + 6 + last - end, Comma);
3003 }
3004 output.splice(n + 6 + last - end..n + 6 + last - end, arg);
3005 output.insert(n + 6 + last - end, Comma);
3006 if !slope && !start_to_end {
3007 output.insert(
3008 n + 6 + last - end,
3009 NumStr::new(Number::from(Complex::new(options.prec), None)),
3010 );
3011 output.insert(n + 6 + last - end, Comma);
3012 }
3013 }
3014 while i < output.len() {
3015 match &output[i] {
3016 LeftBracket if i + 1 < output.len() => {
3017 count += 1;
3018 match &output[i + 1] {
3019 RightBracket => {
3020 output.remove(i + 1);
3021 output.remove(i);
3022 i = i.saturating_sub(1);
3023 count -= 1;
3024 continue;
3025 }
3026 LeftBracket => {
3027 double.push((i, count));
3028 }
3029 Func(s)
3030 if i + 2 < output.len()
3031 && output[i + 2] == LeftBracket
3032 && functions.contains(s.as_str())
3033 && {
3034 let mut n: isize = i as isize - 1;
3035 for d in double.iter().rev() {
3036 if d.0 == n as usize {
3037 n = d.0 as isize - 1;
3038 } else {
3039 break;
3040 }
3041 }
3042 n < 0
3043 || (if let Func(n) = &output[n as usize] {
3044 !functions.contains(n.as_str())
3045 } else {
3046 true
3047 })
3048 } =>
3049 {
3050 double.push((i, count));
3051 }
3052 _ => {}
3053 }
3054 if i == 0 || output[i - 1] == Comma {
3055 brackets.push((i, count));
3056 }
3057 }
3058 RightBracket => {
3059 count -= 1;
3060 if let Some(d) = double.last() {
3061 if d.1 == count {
3062 if output.len() > i + 1
3063 && (output[i + 1] == RightBracket || output[i + 1] == Comma)
3064 {
3065 output.remove(i);
3066 output.remove(d.0);
3067 i = i.saturating_sub(1);
3068 double.pop();
3069 continue;
3070 }
3071 double.pop();
3072 }
3073 }
3074 if let Some(d) = brackets.last() {
3075 if d.1 == count + 1 {
3076 if (i == output.len() - 1
3077 || output[i + 1] == Comma
3078 || output[i + 1] == RightBracket)
3079 && output[d.0] == LeftBracket
3080 {
3081 output.remove(i);
3082 output.remove(d.0);
3083 i = i.saturating_sub(1);
3084 brackets.pop();
3085 continue;
3086 }
3087 if i + 1 >= output.len() || output[i + 1] != Comma {
3088 brackets.pop();
3089 }
3090 }
3091 }
3092 }
3093 Func(s)
3094 if (print
3095 || (i + 1 < output.len()
3096 && (output[i + 1].str_is("rnd")
3097 || output[i + 1].str_is("rand")
3098 || output[i + 1].str_is("epoch"))))
3099 && functions.contains(s.as_str())
3100 && !sumrec.iter().any(|a| a.1 == *s)
3101 && i + 1 < output.len() =>
3102 {
3103 if !matches!(
3104 output[i + 1],
3105 LeftBracket | RightBracket | LeftCurlyBracket | RightCurlyBracket
3106 ) {
3107 output.insert(i + 2, RightBracket);
3108 output.insert(i + 1, LeftBracket);
3109 }
3110 }
3111 _ => {}
3112 }
3113 i += 1;
3114 }
3115 if !err.is_empty() {
3116 return Err(err);
3117 }
3118 if isgraphing && (graph.x || graph.y) && !print {
3119 simplify(&mut output, &mut funcvars, options)
3120 }
3121 while let Some(e) = output.last() {
3122 match e {
3123 Plus
3124 | Minus
3125 | PlusMinus
3126 | Multiplication
3127 | Division
3128 | InternalMultiplication
3129 | Tetration
3130 | Root
3131 | Exponent
3132 | Equal
3133 | NotEqual
3134 | Greater
3135 | GreaterEqual
3136 | Lesser
3137 | LesserEqual
3138 | Modulo
3139 | Range
3140 | Conversion
3141 | NearEqual
3142 | ShiftLeft
3143 | ShiftRight
3144 | And
3145 | Or
3146 | Not
3147 | Xor
3148 | Nand
3149 | Implies
3150 | Nor
3151 | Converse => {
3152 output.pop();
3153 }
3154 Func(s) if functions.contains(s.as_str()) => {
3155 output.pop();
3156 }
3157 _ => break,
3158 }
3159 }
3160 if undf {
3161 return Err("undefined var");
3162 }
3163 if options.graphtype == GraphType::None {
3164 graph = HowGraphing::default()
3165 }
3166 Ok((output, funcvars, graph, false, sumvar))
3167}
3168fn place_multiplier(output: &mut Vec<NumStr>, sumrec: &[(isize, String)], sumvar: &Option<String>) {
3169 match output.last() {
3170 Some(RightCurlyBracket) | Some(RightBracket) => output.push(Multiplication),
3171 Some(Func(s))
3172 if matches!(s.as_str(), "x" | "y" | "w" | "rnd" | "rand" | "epoch" | "@")
3173 || sumrec
3174 .iter()
3175 .any(|a| a.1 == *s || "@".to_owned() + &a.1 == *s)
3176 || sumvar.clone() == Some(s.clone()) =>
3177 {
3178 output.push(Multiplication)
3179 }
3180 Some(Num(_)) | Some(Vector(_)) | Some(Matrix(_)) => output.push(Multiplication),
3181 _ => {}
3182 }
3183}
3184fn can_abs(output: &[NumStr], vars: &[Variable]) -> bool {
3185 if let Some(Func(s)) = output.last() {
3186 !(functions().contains(s.as_str())
3187 || vars.iter().any(|c| c.name.iter().collect::<String>() == *s))
3188 } else {
3189 true
3190 }
3191}
3192fn is_digit(char: char, base: i32) -> bool {
3193 char.is_ascii_digit() || (base > 10 && (97..=97 + (base as u8 - 11)).contains(&(char as u8)))
3194}
3195pub fn simplify(
3196 output: &mut Vec<NumStr>,
3197 funcvars: &mut Vec<(String, Vec<NumStr>)>,
3198 options: Options,
3199) {
3200 let mut i = 0;
3201 while i < funcvars.len() {
3202 let v = funcvars[i].clone();
3203 if !v.0.ends_with(')')
3204 && v.1.iter().all(|v| {
3205 if let Func(s) = &v {
3206 !(matches!(
3207 s.as_str(),
3208 "x" | "y" | "w" | "rnd" | "rand" | "epoch" | "roll"
3209 ) || s.starts_with("rand_"))
3210 } else {
3211 true
3212 }
3213 })
3214 {
3215 if let Ok(n) = do_math(v.1.clone(), options, Vec::new()) {
3216 for f in output.iter_mut() {
3217 if let Func(s) = &f {
3218 if *s == v.0 {
3219 *f = n.clone();
3220 }
3221 }
3222 }
3223 if i + 1 < funcvars.len() {
3224 for fv in funcvars[i + 1..].iter_mut() {
3225 for f in fv.1.iter_mut() {
3226 if let Func(s) = &f {
3227 if *s == v.0 {
3228 *f = n.clone();
3229 }
3230 }
3231 }
3232 }
3233 }
3234 funcvars.remove(i);
3235 continue;
3236 }
3237 }
3238 i += 1;
3239 }
3240 i = output.len();
3241 let mut to = Vec::new();
3242 while i != 0 {
3243 i -= 1;
3244 match &output[i] {
3245 LeftBracket => {
3246 if !to.is_empty() {
3247 if i != 0 {
3248 if let Func(s) = &output[i - 1] {
3249 if !s.starts_with("rand_") && functions().contains(s.as_str()) {
3250 if let Ok(n) = do_math(
3251 output[i - 1..=to[0]].to_vec(),
3252 options,
3253 funcvars.clone(),
3254 ) {
3255 output.drain(i - 1..=to[0]);
3256 output.insert(i - 1, n);
3257 let d = to[0] - i + 1;
3258 to.remove(0);
3259 for t in to.iter_mut() {
3260 *t -= d;
3261 }
3262 continue;
3263 }
3264 to.remove(0);
3265 continue;
3266 }
3267 }
3268 }
3269 if let Ok(n) = do_math(output[i + 1..to[0]].to_vec(), options, funcvars.clone())
3270 {
3271 output.drain(i..=to[0]);
3272 output.insert(i, n);
3273 let d = to[0] - i + 1;
3274 to.remove(0);
3275 for t in to.iter_mut() {
3276 *t -= d;
3277 }
3278 continue;
3279 }
3280 to.remove(0);
3281 }
3282 }
3283 RightBracket => {
3284 to.insert(0, i);
3285 }
3286 Func(s)
3287 if s.starts_with("rand_")
3288 || funcvars.iter().any(|a| a.0 == *s)
3289 || matches!(
3290 s.as_str(),
3291 "x" | "y" | "w" | "roll" | "rnd" | "rand" | "epoch"
3292 ) =>
3293 {
3294 to.clear();
3295 }
3296 _ => {}
3297 }
3298 }
3299}