kalc_lib/
parse.rs

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}